I just "fixed" a bug in the following lines of PHP:
$value = 1091.09; // the failing test case
$prop = sprintf('%013d', $value * 100);
by adding those lines:
$cents = $value * 100; // $cents is now 109109
$cents = round($cents, 2); // $cents is still 109109
$prop = sprintf('%013d', $cents);
The result for the former block is "0000000109108"
, while that of the second one is "0000000109109"
, which is correct.
Note that I added both lines to be able to view each step in the debugger separately. It also works if I skip the first line, thus writing:
$cents = round($value * 100, 2); // $cents is now 109109
$prop = sprintf('%013d', $cents);
So, apparently, the round()
function does something invisible to the value that makes it work differently with sprintf()
. What is it?
Were this a proper language, I would probably know by looking at the data types. Here, I don't even know what they are.
it maybe not as simple...
php > $value = 1091.09; print sprintf('%f', $value);
1091.090000
php > $value = 1091.09; print sprintf('%f', $value*100);
109109.000000
php > $value = 1091.09; print sprintf('%f', (int)($value*100));
109108.000000
One would expect to see all these '999999' in first two results.
Additionally:
php > $value = 0.09; print sprintf('%f', $value);
0.090000
php > $value = 0.09; print sprintf('%f', $value*100);
9.000000
php > $value = 0.09; print sprintf('%f', (int)($value*100));
9.000000
(NOTE: same result of 0.009 and 0.9)
Bottom line, @Mihai is probably right in his answer, but it seems that these "approximate" float numbers (with infinite number of 99999's) exist some where deep inside bowls of floating point arithmetic unit and influence PHP level calculations only in some very particular cases.