As I'm sure many of have experienced, I'm having a little issue with floating point math - I fixed the issue in JavaScript, however whilst it seems ok in PHP I wanted to make sure it could be relied upon as it's slightly different to the JS version.
JavaScript:
var item = 25.00;
var postage = 24.99;
((item + postage) * 100) // 4998.999999999999
Obviously I don't want this, I want 49.99
, so I change it to this:
((item + postage) * 100).toFixed(0) // 4999 (string)
Then for good measure I change it to this:
provideFloat((book_price + shipping_cost) * 100).toFixed(0)) // 4999 (float)
function provideFloat(num) {
return parseFloat(num.replace(/,/g, ''));
}
Now, I need to test against this number on the PHP side to see if they match, so I tried this (for example):
PHP:
$item = 25.00;
$postage = 24.99;
echo ((item + $postage) * 100); // 4999
So as you can see, a different result than JavaScript - can I rely on this being "right" for comparisons sake and not ending up with something like 4998.999999999999
?
For interests sake I tried to apply a similar technique that I did with JavaScript with a similar approach that JS uses in their toFixed
function, with:
$number = (($item + $postage) * 100);
$expo = pow(10,0);
$number = intval($number * $expo) / $expo;
echo $number; // 4998
...and I get 4998
whereas JS got 4999
- so should I stick with what actually got the 4999
result? Can this be relied upon?
..or do you have to go to extremes like this?
$res = (($item + $postage) * 100);
$res = (float) number_format($res, 0, '.','');
echo $res; // 4999
My use case is I need to turn floating point numbers (dollars) into cents and then compare them from client side to server end.
Simple answer: No. You can't rely on floating point precision in PHP, or any language. While it may work for this example, there will be cases where it will not match.
If precision is required, either use integers for math or use bcadd() with strings.
If close enough is fine, you should be able to get away with round(). number_format() is not desirable for comparisons, only formatting (see thousand separator).