The usual advice to handle money and other decimal numbers where accuracy is crucial is to either use integers or strings (plus arbitrary precision libraries) and it makes sense if you understand how floating point maths work. However, I don't have at hand any specific example to illustrate this, as every wrong calculation I've spot in the wild was due to some other mistake: naive comparisons using ==
, lack of proper rounding when displaying results, blatantly wrong logic (e.g. calculating taxes with an inconsistent algorithm that also doesn't work on paper)... I've done some research and results either only apply to C/C++ (float/double having different precision) or were mere elaborations on why you can't trust two floats to be equal.
Can you share a self-contained PHP code snippet with carefully selected floating point figures and a correct algorithm that renders an incorrect result explicitly caused by floating point limitations?
Disclaimer: I don't intend to argue, refute or debunk anything, I honestly need an example for my toolbelt.
The question makes little sense because that isn't how floating point errors work.
Inaccuracies are tiny. They happen in remote decimals and they're only noticeable when you require very high precision levels. After all, IEEE 754 powers a vast majority of computer systems and it offers an excellent precision. To put it in context, 0.1 kilometres expressed as float is 0.100000001490116119384765625, what makes accurate up to 1/10 of a µm if I didn't get maths wrong.
There probably isn't a set of carefully chosen figures and a real-life calculation you'd be expected to use PHP for (an invoice, a stock exchange index...) that renders incorrect results no matter how careful you are with precision levels. Because that's not the problem.
The problem with floating point maths is that it forces you to be extremely careful on every step and it makes it very easy for bugs to slip in.
For applications where accuracy matters, you can write correct software using floats, but it won't be as easy, maintainable or robust.
Original answer:
This is the best I've got so far (thanks to chtz for the hint):
// Set-up and display settings (shouldn't affect internal calculations or final result)
set_time_limit(0);
ini_set('precision', -1);
// Expected accuracy: 2 decimal positions
$total = 0;
for ($i = 0; $i < 1e9; $i++) {
$total += 0.01;
// It's important to NOT round inside the loop, e.g.: $total = round($total + 0.01, 2);
}
var_dump($total, number_format($total, 2));
float(9999999.825158669)
string(12) "9,999,999.83" // Correct value would be "10,000,000.00"
Unfortunately, it relies on the accumulation of a very large number of precision errors (it needs around 1,000,000,000 of them to happen and it needs more than 4 minutes to run in my PC), so it isn't as real-life as I would have liked, but it certainly illustrates the underlying issue.