2

In base to this example: Dealing with multiplying fractions in solidity

I am adding th DSMath correctly. I can operate and compile with integers but if I try to compile a contract with any decimal inside the functions Remix dont let me compile: (for ex) this function

function theCalc(uint aNumber) public view returns(uint){
    return wmul(aNumber, 3.1416);
}

Remix error: TypeError: Invalid type for argument in function call. Invalid implicit conversion from rational_const 3927 / 1250 to uint256 requested. return wmul(aNumber,3.1416);

Any idea how could I work with a fixed decimal number in my solidity calcs? Thank you.

2 Answers 2

0

The error message indicates that the calculation is working as is. Your actual problem is that 'theCalc' is declared in a such way that expects an integer to be returned ('returns(uint)').

0

The classic way of dealing with decimals involves upscaling and downscaling. This doesn't necessarily involve the DS_Math library, we'll try and circle back to that.

Upscaling and Downscaling

While it is true that Solidity doesn't have decimal values, you can upscale a value by multiplying it by some constant, then multiply by your decimal value as a whole integer (pi would become 31416 in the OP's example), and then downscale by dividing by the same constant multiplied by in the beginning. 1e18 seems to be a common constant (at least if you're using a suitably large uint, such as uint256). That would look something like:

function multiplyByPi(uint256 num) public view returns(uint256) {
    uint256 scaledSolution = num.mul(1e18).mul(31416);
    return scaledSolution / 1e18
}

DS-Math

DS-Math is a library from DappHub that provides both overflow safe operation, and something they describe as representations of fixed point decimal numbers. Upon inspection, the second part of that sentence does not mean that you can type in something like 3.1416 and have the compiler understand that. Under the hood, it looks like DS-Math is doing the same thing we discussed above - if you are using Wads it's scaling by 18 places, and if you use Rays, by 27. So if you would like to use wad math (as indicated by using wmul in your question), you could do something like the following:

function theCalc(uint256 aNumber) public view returns(uint256){
        uint256 pi = 3141592653589793284;
        return wmul(aNumber, pi);
}

This might not answer all of your needs. If you would input 1 into the function above, it would output 3, since Solidity, even with DS-Math, does not have decimals. It expects you to kind of keep track of the first 18 places as your decimal space, at least as far as I can tell. In that paradigm, putting 1e18 (as a 1 with 18 zeroes, you might not be able to actually type in 1e18) as the argument would be akin to putting in 1, and the function would return 3.14... to 18 decimal places.

In short, while this is likely not the answer you were looking for, as of this writing (March 2021), DS-Math does not allow you to write a decimal such as 3.14 and use it in mathematical operations. It does allow you to upscale to 18 places with wads, and 27 with rays, but all this does is upscale by either 1e18 or 1e27.

Hope this helps!

1
  • 2
    Thnks. Yes, I discovered this way too but the next problem now is that Solidity cant work with numbers biger than 10e77 ... Frustrating! I think that instead of solidity it should be called fragility
    – JTCon
    Commented Mar 22, 2021 at 17:07

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.