Bug #61108 [Nab]: string math with vast differential numbers yield invalid math.
| From: | rasmus@php.net | Date: | Thu, 16 Feb 2012 18:18:28 +0000 |
| Subject: | Bug #61108 [Nab]: string math with vast differential numbers yield invalid math. | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-167575@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=61108&edit=1
ID: 61108
Updated by: rasmus@php.net
Reported by: qphoria at gmail dot com
Summary: string math with vast differential numbers yield
invalid math.
Status: Not a bug
Type: Bug
Package: Math related
Operating System: Windows/Linux
PHP Version: 5.3.10
Block user comment: N
Private report: N
New Comment:
If you change your output precision setting you will see it. But that is just for
final output purposes. If we rounded every float internally you would lose a lot
of precision since all these would pile up and cause actual math errors. But yes,
it does mean you have to be careful if you are trying to do strict equivalence
checking on floats. But that is the same for most languages that use the
underlying float implementation. There are higher-level ones, of course, but they
are quite a bit slower.
Previous Comments:
------------------------------------------------------------------------
[2012-02-16 18:05:14] qphoria at gmail dot com
I guess this would be a more relevant read:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Seems to clear it up more.
------------------------------------------------------------------------
[2012-02-16 18:00:29] qphoria at gmail dot com
It seems the proposed solution is that we should always add
round($y,2)
to any string math. But if php is going to return exact numbers to the variable
dump, but hide the "real" value in the back end.. then what is the point? The
bug may not be with floating, but instead with the way php outputs the variable.
If we are meant to always round string math, then you may as well add the
round() function to the last step of the string math result in the php exe and
spare the rest of us. Nobody can trust (float) now because what php outputs
isn't really what it uses to calculate. Unless there is some way to find out
that hidden "epsilon" value.
------------------------------------------------------------------------
[2012-02-16 17:50:17] qphoria at gmail dot com
Perhaps, but then why wouldn't the additional decimals show in the variable?
The initial string math should have returned:
20.22000003
if that was the case.
I would expect to see:
$x = 20.22
: double = 20.22
$y = ("10.10" + "10.12");
: double = 20.22000030
or
20.22e08 or something
------------------------------------------------------------------------
[2012-02-16 17:24:51] rasmus@php.net
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-02-16 17:18:05] qphoria at gmail dot com
Description:
------------
Tried this on the latest 5.3.10 and also on 5.2.17
It is a bit difficult to put into words, but math with varying string-number
sizes calculates wrong.
Simply put:
THIS IS CORRECT:
-----------------
$x = 20.22
: double = 20.22
$y = ("10.10" + "10.12");
: double = 20.22
$x == $y
: bool = TRUE
THIS IS BUGGED:
-------------------
$x = 20.22
: double = 20.22
$y = ("19.10" + "1.12"); //20.22
: double = 20.22
$x == $y
: bool = FALSE
For some reason, if you have a wide number spread in the string math, the
boolean fails, even though they are both shown as float/double numbers
The simple fix is to wrap round() around the string math. Can't really explain
it.
Test script:
---------------
<?php
$x = 23.36;
$y = ("21.42" + "1.94");
if ($x < $y) {
echo "math fail<br/>";
} else {
echo "math win<br/>";
}
var_dump($x, $y);
echo "<br/>";
$x = 23.36;
$y = ("10.36" + "13.00");
if ($x < $y) {
echo "math fail<br/>";
} else {
echo "math win<br/>";
}
var_dump($x, $y);
?>
Expected result:
----------------
I expect to see:
math win
float(23.36) float(23.36)
math win
float(23.36) float(23.36)
Actual result:
--------------
What I really see is:
math fail
float(23.36) float(23.36)
math win
float(23.36) float(23.36)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=61108&edit=1