There has been a lot of progress since the beginning of Ethereum about best practices in Solidity. Unfortunately, I have the feeling that most of the knowledge is within the circle of experienced people and there aren’t that many online resources about it. That is why I would like to start this tutorial series called Solidity Design Patterns.
We are going to start it off by one straight-forward about math. I hope everybody is using SafeMath or something similar by this point in time. Nonetheless, there are still things to consider.
Do your multiplication before division!
console.log((30 * 100 * 13) / 13)
Now, let’s do the division first. After all,
abc/c == a/c * bc , right?
console.log((30 / 13) * 100 * 13)
By doing all our multiplications first, we mitigate rounding related issues as much as possible. The computations can be much more complex and forming them into a multiplication first formula can be challenging at times.
Not always sufficient!
Sometimes this is not good enough. If we are computing pay-outs for Ether, then it is most probably fine. After all, who cares about missing out on a single Wei in payment? As long as the computations are consistent and you’re not relying on all payout summing up to exactly the same amount of Wei as expected, you are fine.
This does not mean that it is always fine. Depending on your use case, you might want to favor an implementation using a numerator and denominator.
uint256 numerator = 30 * 100 * 13;
uint256 denominator = 13;
You can always store the number pair and do your computations according to proper math. In most cases, having a number rounded down will be fine though. Just know that this can happen and deal with it when you have to.