Skip to content
Advertisement

PHP Rounding Float

I’m working on a system where I need to round down to the nearest penny financial payments. Naively I thought I would multiply up by 100, take the floor and then divide back down. However the following example is misbehaving:

echo 1298.34*100;

correctly shows:

129834

but

echo floor(1298.34*100);

unexpectedly shows:

129833

I get the same problem using intval for example.

I suspect the multiplication is falling foul of floating point rounding. But if I can’t rely on multiplication, how can I do this? I always want to round down reliably, and I don’t need to take negative amounts into consideration.

To be clear, I want any fractional penny amounts to be stripped off:

1298.345 should give 1298.34
1298.349 should give 1298.34
1298.342 should give 1298.34

Advertisement

Answer

Since you mention you only use this for displaying purposes, you could take the amount, turn it into a string and truncate anything past the second decimal. A regular expression could do the job:

preg_match('/d+.{0,1}d{0,2}/', (string) $amount, $matches);

This expression works with any number of decimals (including zero). How it works in detail:

  • d+ matches any number of digits
  • .{0,1} matches 0 or 1 literal dot
  • d{0,2} matches zero or two digits after the dot

You can run the following code to test it:

$amounts = [
    1298,
    1298.3,
    1298.34,
    1298.341,
    1298.349279745,
];
foreach ($amounts as $amount) {
    preg_match('/d+.{0,1}d{0,2}/', (string) $amount, $matches);
    var_dump($matches[0]);
}

Also available as a live test in this fiddle.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement