Pull Requests

History

Floating point values have a limited precision. Hence a value might
not have the same string representation after any processing. That also
includes writing a floating point value in your script and directly
printing it without any mathematical operations.
If you would like to know more about "floats" and what IEEE
754 is, read this:
http://www.floating-point-gui.de/
Thank you for your interest in PHP.
.

[2012-04-21 10:11 UTC] ubuntu at spacetrace dot org

so why does php round 7.005 down to 7.00 while it rounds 8.005 correctly up to 8.01 ?
and why from 16 on again wrong and from 32 on again correct, from 64 on again wrong but now
not a change from 128 on?

Did you visit the site we provided that explains this? What you think is 7.005 is
actually represented as 7.004999999999999999 whereas 8.005 is
8.005000000000000000001
That's what limited precision means. Go read http://www.floating-point-gui.de/
for a complete explanation.

[2012-04-21 17:28 UTC] ubuntu at spacetrace dot org

ah ok,
that explains the behaviour.
wouldnt it be senseful, if php would always floor the float variable then?
or at least throw a notice error, if you parse a float through "%.2i"?
i understand this is not a senseful programm-style. cause you get an unpredictable behaviour.
if money_format() would round down always, then it would be predictable
are there more functions that would show the same behaviour like in this example? what about printf()

How does always rounding down fix anything? What if you are trying to do 3.0 but
you actually get 2.999999999999999, if you always round down you would get 2
instead of 3.

[2012-04-21 21:21 UTC] ubuntu at spacetrace dot org

now that i uderstand how floating numbers work in computers, this is sure a real bug then:
they say:
"a tiny error in the 17th decimal place doesn’t matter at all "
here the bug is at the 3rd place!
and:
" If you just don’t want to see all those extra decimal places: simply format your result rounded to a fixed number of decimal places when displaying it."
this is what i did here and that caused the bug
think about it: NO ONE wants this behaviour if he or she uses '%.2i' in a function
This function should be fixed, so it rounds mathematically correct like the round() function.
If not, then it should throw an error like
"cannot shorten a float variable with this syntax" or so.

Rounding errors compound when you loop like that. There is still no bug here.

[2012-04-21 21:54 UTC] ubuntu at spacetrace dot org

money_format('%.2i',1.005) results in 1.00
and
money_format('%.2i',7.005) results in 7.01
this is definitely a bug. you only showed me, the reason, how the bug was created. but it should still be solved!
Or, if you say, the syntax is not correct, cause you provoke an unpredictable behaviour with '%.2i' then shouldnt that throw an error notice at least?
why cannot the php-supporters use the same algorythm, like in function round(), where there IS rounded correctly

This is getting a bit tiresome. There is no bug here.
Maybe you will understand it this way. Try running this:
<?php
ini_set('precision',32);
$ns = array(1.005, 7.005, 8.005);
foreach($ns as $n) {
echo "$n ".money_format('%.2i', $n)."\n";
}
The output on my machine is:
1.004999999999999893418589635985 1.00
7.004999999999999893418589635985 7.00
8.0050000000000007815970093361102 8.01
That is, 1.005 can't actually be represented accurately and it ends up being
slightly below 1.005 which means when you round it you get 1.00. And 8.005 ends
up being represented as slightly larger than 8.005 so when you round it you get
8.01. It makes perfect sense. Simply add a fuzz factor to your floating point
values to the appropriate precision you care about. Or, as most people know,
when dealing with money, don't use floating point at all. Work in integers.

[2012-04-22 20:21 UTC] ubuntu at spacetrace dot org

i am sorry, i didnt want to do any harm.
i perfectly understood it before already.
But what do you think about my suggestions?
1. a notice error
or
2. round it like the round() function

There is no efficient way to "notice the error"
If you want slow and accurate floating point manipulation it is available via the
arbitrary precision extensions like bcmath and gmp.

[2012-04-22 22:45 UTC] ubuntu at spacetrace dot org

maybe an efficient way would be to see if the desired amount of digits is less than the amount of digits in the float.
in my example where i tried to show 1.005 with only 2 fractional digits, the notice could be like:
"Error: input float exceeds maximum number of fractional digits"
this would save thousands of hours of debugging worldwide.
i am so keen on this issue, cause it cost me already about 100 hours of work to find out what was the cause, why in my project my bills every now and then where not correctly rounded.
it is a stupid bug really hard to track and i am sure am not the only one that had this problem.
if php would throw a notice, that would save lots of hazzle for not-so-experiensed programmers.
how can you know, that you shouldn't use floats in money_format. this is a kind of secret knowledge right now especially cause the manual says: "string money_format ( string $format , float $number )"

No, that won't work. Often the value comes from expressions that always generate
lots of digits. eg. number_format('%.2i', 1/3)
What would you expect that to do? You wold get a notice every single time even
though there may not be any relevant loss of precision.
There are just certain things you need to eventually learn when you start
programming.

[2012-04-22 23:15 UTC] ubuntu at spacetrace dot org

how does the function round(7.005,2) do the trick to get 7.01? is it so much slower than how money_format does it?

[2012-04-26 09:38 UTC] ubuntu at spacetrace dot org

could you please set the Status back to "Bug"
all people i talked to, said, that this should be solved. cause it causes follow-up bugs in your applications that are very hard to find, cause they happen so seldom

[2012-04-26 10:07 UTC] ubuntu at spacetrace dot org

The same bug is in
sprintf("%01.2f",7.005);
which results in
7.00
while
sprintf("%01.2f",8.005);
results in
8.01

Please stop. This is not a PHP-specific issue. This is just how floating point
works in computers. You will need to learn how to deal with it. For example,
compile this C program:
#include <stdio.h>
int main(char *argv[], int argc) {
printf("%01.2f\n",7.005);
printf("%01.2f\n",8.005);
}
cc f.c -o f
then run it:
./f
you get:
7.00
8.01
Which is exactly the same as the PHP results. PHP is a thin layer over C.