Hi, internals
I'm working on fixing a bug in round()
. There was a discussion about what should be considered an edge case.
For example, 0.285
is internally 0.28499999999999998
. Should this be considered an edge case? Or is it not an edge case? Regarding this issue, in 2008, the following RFC adopted the policy that 0.285
is considered an edge case''.
https://wiki.php.net/rfc/rounding
Here is a PR for changes based on the contents of the above RFC.
https://github.com/php/php-src/pull/12268
However, since FP is just FP, there is an opinion that it is wrong to treat 0.285
as an edge case. This is PR based on such opinions.
https://github.com/php/php-src/pull/12291
A new RFC is required to change what was determined in the previous RFC, so I would like to hear everyone's opinions first.
Best regards.
Saki
Hi
For example,
0.285
is internally0.28499999999999998
. Should this be considered an edge case? Or is it not an edge case? Regarding this issue, in 2008, the following RFC adopted the policy that0.285
is considered an edge case''.
https://wiki.php.net/rfc/rounding[…]
A new RFC is required to change what was determined in the previous RFC, so I would like to hear everyone's opinions first.
As I've previously said in the GitHub comments, I'm in favor of removing
the complicated pre-rounding logic. Attempting to "guess" what the user
might have wanted will only make the floating point imprecision worse
than it already is.
The internal representation 0.28499999999999998 is the one that is the
"average" value of all the real numbers that map to it, thus minimizing
bias. Interpreting it as 0.285 already adds a bias towards larger values
and then rounding it to 2 decimal digits will result in 0.29, despite
the majority of numbers that are internally represented as
0.28499999999999998 being correctly rounded to 0.28.
I believe treating 0.28499999999999998 as 0.28499999999999998 and not
0.285 will be the least surprising behavior for folks that know how
floating point numbers work. It would also be consistent with 'printf()'
(testing with both 0.285 and 0.295 to show it doesn't just round to even):
php > var_dump(round(0.295, 2));
php shell code:1:
double(0.3)
php > printf("%.2f", 0.295);
0.29
php > var_dump(round(0.285, 2));
php shell code:1:
double(0.29)
php > printf("%.2f", 0.285);
0.28
Best regards
Tim Düsterhus