46

I just started writing some solidity and I noticed that there are no decimal values such as double or float.

What do you guys do when you need to return send to a wallet let's say 1.57 ether? Or when you need to calculate 1/2 = 0.5?

I'm very confused - I tried doing something like var a = 0.5; but it gives me an error that says

Invalid literal value.

1

6 Answers 6

46

Math in Solidity is done entirely using fixed-point. For ether, there's no need to use fractional values - all values are represented in wei, which is the smallest unit of ether.

If you want to send 0.5 ether, you can instead specify your literal as "500 finney", which will be converted into wei:

msg.sender.send(500 finney);

or:

msg.sender.send(1 ether / 2);

which are both exactly equivalent to:

msg.sender.send(500000000000000000);

If you want to multiply a value by a fraction (eg, 2/3), first multiply by the numerator, then divide by the denominator:

value = (value * 2) / 3;

It's worth noting, too, that floating point for financial math is a terrible idea - it introduces rounding errors that easily lead to lost money.

2
  • 2
    @NickJohnson Let me ask you just one more thing. So when a wallet sends funds to a contract, if I call the msg.value function? This will return me the amount of ether represented in wei right? So by default in the contract I'm always talking about wei?
    – sfrj
    Commented Apr 14, 2016 at 16:02
  • 3
    @sfrj That's right. Commented Apr 14, 2016 at 16:11
6

The Fixed Point Numbers documentation has a warning which says:

Fixed point numbers are not fully supported by Solidity yet. They can be declared, but cannot be assigned to or from.

The warning at the bottom of Rational and Integer Literals says:

Division on integer literals used to truncate in earlier versions, but it will now convert into a rational number, i.e. 5 / 2 is not equal to 2, but to 2.5

1
  • 5
    So what can you do with them if they can't be assigned to or from? Commented Jul 4, 2018 at 22:48
5

There is a mention of Reals as a value type in the Solidity documentation.

Edit: It was actually the old documentation, on Github. No mention in the ReadTheDocs-documentation.

Reals are formed similar to integers except that they include a decimal point and at least one number on either side of it. An example would be: 3.14159265 and 42.000001.

I get compiler errors when attempting to use these, so they might not be implemented yet.

1
  • 1
    Fixed point / rational numbers are back.
    – Tom Hale
    Commented Oct 5, 2017 at 12:03
4

For 1.57 ETH, note that in Ethereum all Ether amounts are measured in Wei, and 1 Ether is just 10^18 Wei, so 1.57 ETH is basically 1570000000000000000 Wei, i.e. integer number.

For 1/2 = 0.5 you probably need some kind of fixed point library, such as ABDK Math 64.64. It operates with binary fixed point numbers (64 binary digits after dot) and has all basic math operations.

1

Also, you could use ufixed128x18 for your decimals value like:

ufixed128x18 public decimals_val;

and set value (like Fee) for this state variable.

0

you can use import "@openzeppelin/contracts/utils/math/SafeMath.sol";

this in your smart contract and then do calculations like:

Normal Math: 0.56 * x Solidity: (x.mul(56))/100;

Normal math: 56 + x; Solidity: x.add(56);

This could be a better approach for dealing with decimals coz safeMath handles overflows issues that could arise

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.