After spending an hour trying to find out why a PHP script gave me incorrect output, it turned out that a loop ran one iteration short in one particular case.
To explain what is going on: a version number (2-digits, e.g. 1.5 or 2.0) is read from an XML-attribute and is multiplied by 100. The script later iterates over a defined range of version number multiples.
It turns out that 410 == 409, which gives a funny surprise if you compare a counter that increments in steps of 10 against that value.
Which brings me to my question: Am I fundamentally understanding something wrong? Certainly, 4.1, 100, and 410 should all be well-representable as float and should be well-convertible to int without rounding errors?
However, on my system (with PHP 5.3.2 CLI, Zend Engine 2.3.0), the following test case
<?
$a = 100 * 4.1;
$b = (string) $a;
$c = (int) $a;
$d = (int)(string) $a;
var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);
?>
outputs:
float(410)
string(3) "410"
int(409)
int(410)
I am now doing a (int)(string) conversion which works, but this is kind of a nasty hack that isn't pretty and doesn't quite feel right.
Is there a better (correct, no-hack) solution to get a precise result?
You usually can not see, if a value is well-convertible into a float just by looking at it. Read The warning in the manual for an example.
Your problem is in the first line:
$a = 100 * 4.1;
The float literal 4.1 does not, in fact, have the value 4.1, and so the result of multiplying it with 100 is not 410 but a little less. Apparently, casting to string rounds up, but casting to int rounds down.
To get the decimal math you expect, use the BC Math functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With