# How to do Solidity percentage calculation?

I'm trying to calculate a percentage of a number in solidity with the following code.

The percentage is technically basis points (10000ths, instead of 100ths) because I want decimal percentage values.

uint128 is enough for expressing the normal numbers, but to try to avoid precision errors, I cast the values to int256 for the calculation.

``````pragma solidity 0.4.24;
contract PercentageCalc {
uint128 public bp = 185; // 1.85% in basis points (parts per 10,000)

function calculatePercentage(
uint128 theNumber
)
public
view
returns (uint128) {
return uint128(int256(theNumber) / int256(10000) * int256(bp));
}
}
``````

The problem is if I input `111111111111111111` as `theNumber`, the output is `2055555555555535` instead of the desired output of `2055555555555555` (what I get by doing the calculation with for example BigNumber.js).

I'm guessing it is some precision error I have overlooked. How do it get the desired output of `2055555555555555`?

• MULTIPLY BEFORE YOU DIVIDE!!! (and make sure that the multiplication doesn't overflow of course). Aug 2, 2018 at 13:30

Do the multiplication first:

``````return theNumber * bp / 10000;
``````

The problem with dividing first is that the result is an integer, so it chops off anything that drops behind the decimal point.

The thing to watch out for when multiplying first is integer overflow, so make sure your numbers are in an appropriate range where such multiplication won't exceed the maximum value of your data type.

While method, suggested by @user19510, works well in simple cases (probably including your case), it has one important drawback: the intermediary multiplication may overflow even when final result does fit into result type. For example, this method cannot be used to calculate 3% of 2^256 - 1, while both, 2^256 - 1 and 3% of it do fit into Solidity `uint` type. So as a general method I would recommend using the following function:

``````// Calculate x * y / scale rounding down.
function mulScale (uint x, uint y, uint128 scale)
internal pure returns (uint) {
uint a = x / scale;
uint b = x % scale;
uint c = y / scale;
uint d = y % scale;

return a * c * scale + a * d + b * c + b * d / scale;
}
``````

This implementation overflows ONLY when final result does not fit into `uint` type. Note, that `scale` is `uint128` rather than `uint`. Of cause, in production code, all `+` and `*` operation should be done via SafeMath. I used plain operators here to make code easier to read.

The idea is that we to the following substitutions:

``````x = a * scale + b
y = c * scale + d
``````

where `b < scale` and `d < scale`. Then:

``````x * y / scale =
(a * scale + b) * (c * scale + d) / scale =
(a * c * scale^2 + (a * d + b * c) * scale + b * d) / scale =
a * c * scale + a * d + b * c + b * d / scale
``````

As long as `scale` fits into `uint128` and both, `b` and `d` are less than `scale`, then `b * d` fits into `uint256` so no intermediary overflow is possible.

If you need to round up, replace `b * d / scale` with `(b * d + scale - 1) / scale`. If you need to round to the closets integer, use `(b * d + scale / 2) / scale`.

Here is a drop in solution with information from other answers for reward percentage calculation.

`````` uint256 result = ((amount * interestRate * timeDiff) / lockPeriod) / 1e4;
``````

where interestRate percentage is set like this.

``````uint256 public interestRate = 2000; //20 Percent

``````