Rounding fixed point integers

If I'm using fixed-point arithmetic to represent rates, for example, 2% in ray (27 decimal precision) would be 102000000000000000000000000000.

If I had a rate like 101333333333333333333333333333 (1.33%), how can I round it to the nearest 0.25%?

I would want 10125000000000000000000000000 (1.25%) to be the result.

• Could you be more specific? Do you always need to round to the nearest .25% interval (.00, .25, .50. 75)? Always round up or down? Apr 3, 2021 at 0:43
• Yes, the nearest .25% interval. So for example with 1.3% it’d go to 1.25%, 1.4% to 1.5%. Although I’d accept a solution that rounds down too e.g. 1.3% and 1.4% both rounding to 1.25%. Apr 3, 2021 at 2:37

They are integers so you can round them like they were integers.

To round integer A to B proceed as following trunc(A / B) * B.

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.0 <0.9.0;

contract Test  {

uint256 public one = 10**27;
uint256 public two_percent = 10**27 + 0.02 * 10**27;
uint256 public rate = 10**27 + 0.01 * 10**27 + uint256(0.01 * 10**27) / 3;

uint256 public round = 0.0025 * 10**27;

function roundDown() public view returns (uint256) {
return ((rate / round) * round);
}

function roundUp() public view returns (uint256) {
return (((rate + round - 1) / round) * round);
}
}

• I was doing some testing with 1014999999999999999992500000 and the result was 1012500000000000000000000000. I would have expected the result to be 101500000000000000000000000. How can this be remedied? May 12, 2021 at 16:36
• @rosendin The trick is to add round - 1 before dividing by round. So the formula will be (rate + round - 1) / round then multiplying by round should give you the scale desired. So (((rate + round - 1) / round) * round) is the final formula.
– Ismael
May 12, 2021 at 17:24