Edit report at https://bugs.php.net/bug.php?id=61108&edit=1
ID: 61108 Updated by: ras...@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] ras...@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