php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #51396 Math is Unreliable
Submitted: 2010-03-26 00:36 UTC Modified: 2016-06-12 06:34 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: codeslinger at compsalot dot com Assigned:
Status: Not a bug Package: Math related
PHP Version: Irrelevant OS: any
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: codeslinger at compsalot dot com
New email:
PHP Version: OS:

 

 [2010-03-26 00:36 UTC] codeslinger at compsalot dot com
Description:
------------
is math accuracy important?
no I am not talking about round-off errors.  I am talking about the fact that most of the time, php correctly says that 2+2 = 4, but that sometimes it says that 2+2 = 0.

What if your paycheck was being printed by a php program and you discovered that the math is inaccurate, would you care then?

I ask these questions because I previously reported this bug because it occurred in a billing system that I wrote, but nobody considered that bug important enough to pursue it.  Too complex, too hard to reproduce.  whatever.

Well, I have now encountered this bug again, with a much simpler program.  and this program demonstrates that math in php is completely and totally untrustworthy.  Does anyone care that fundamental functionality is unreliable?  What good is a programming language that can't do math?

php passes trivial math tests just fine; it's only when you use it in complex real-world ways that it starts failing.  No these aren't binary base conversion errors, I'm guessing that this is memory corruption, so far I've only observed it with thousands of calculations.  But the trivial programs I wrote in an attempt to reproduce the problem never succeeded in failing.  I can only get it to fail when I'm doing real-world / complex stuff

Characteristics:
This is not a bug in the php program; under specific conditions - described below - the php program does run correctly.

The main problem occurs when a float is converted to a string by a program that makes heavy use of arrays.

It's not an out of memory condition, I have successfully stress tested an array with one million items, but I am seeing it fail with only a thousand items.

When it fails, the failure it totally repeatable, it always fails in exactly the same place in exactly the same way.  And yet there is no discernible pattern to the failure, the trigger condition is unpredictable, it seems to depend on the actual data values.

It is not a hardware issue, this has been observed on multiple machines.  Also my main computer has had extensive memory diagnostic and hard disk tests run on it without finding any problems.

It is not operating system specific, this failure has been observed on both Linux and Windows.

It is not an FDIV bug.  This Pentium chip is verified to not have that bug.

Different versions of php are triggered by different sequences of events.  But all of them fail in some way.

I have two programs, both of which fail, but the specifics of the failure vary depending on which version of php they are being run on.

One program is a billing system, it is large and complex and proprietary and the data is confidential and it uses several external libraries. The other program generates a Koch Snowflake (a type of graphics fractal).  It is small and has no required dependencies and I am happy to make it's source code available.

Both fail with the same or similar math errors but the behavior is not identical.

The billing system *appears* to run fine on Windows PHP 5.2.5 (standard build as provided by php.net).  The billing system is in daily use and no errors have been reported... so far...

At one point it was decided to upgrade to PHP 5.2.9 (standard build from php.net).  The billing system passed the preliminary testing with dummy data and the php upgrade was deployed to the field.  

Result:  Can you spell NIGHTMARE?!!!  I knew you could...  
Many instances of invalid statements being created.  The math errors were repeatable.  We are talking simple arithmetic about 90 percent of it is just adding, with a few multiplications.  This was entered as bug #47716 

Everyone was downgraded back to php 5.2.5  and the bug report was blown off.

I also confirmed that the bug existed in 5.2.11
I  assumed that the bug did not exist in 5.2.5

An attempt was made to test 3.x but that was impossible because the billing system requires various libraries which are not available for version 3 of php.
And that is where things have sat until now.

New program, Koch Snowflake generator.
I'm doing some experiments with 3d graphics.  This was written as a study in how to do it.  I ran into exactly the same math -- string conversion bug, that the billing system ran into.

But the Koch Snowflake program Fails on Ubuntu Linux with php 5.2.4!!!

What triggers this bug is a very complex unpredictable sequence of events.  And yet the failure is totally repeatable.  Being a fractal, it has an outer loop of iterations which determine the complexity of the object.  When I run 4 outer loops the program works fine, when I run 6 outer loops the program also works fine -- thus proving that it is not running out of memory.  But when I run 5 outer loops the program fails and it always fails at item 7747.

But wait there is more.  Because when I run the Koch program on php 5.2.9 on Linux, it does not fail with the string conversion error.  

What this tells me is that my assumption was wrong, this bug does exist in version 5.2.5 and that my billing system is sitting on a ticking bomb for which the actual trigger is unpredictable.

And that is why I am trying to get someone, anyone, to please pay attention to this bug. It is very very very serious.  If this bug is not fixed I am going to have to abandon php altogether.

The stock answer that people should upgrade php as the solution to all of their problems fails to take into account real-world realities.  When the day comes that you can get all of the libraries to upgrade, and when you can get all of the hosting providers to upgrade and you can get most of the Linux distros to upgrade.  Then, on that day, you can indeed expect that people should use a newer version of php as the solution to their problems.  I would indeed love to be able to run a more current version of php, but as long as I am dependent on certain libraries and I must lease services from various hosting providers I am constrained by what is actually available in the real-world.  And currently what is the most widely deployed version in the real-world is 5.2.4.

Besides which, as far as I can tell, this bug exists in all versions of php since at least 5.2.4.  I see no indication of it ever having been fixed in any version of php.  But the difficulty is that the behavior does change, the specific trigger sequence does change depending on which version of php is being used.  Someone really needs to track down the actual cause of this problem in a version that can reliably reproduce the failure and not make assumptions that it does not exist in other versions just because it was not triggered.



Test script:
---------------
here is a url to the Koch snowflake program

http://www.compsalot.com/phpbug/kochsnowflake/


see the source code for details of how to run the program.
Please keep in mind that triggering this bug is very finicky.  The billing program fails in 5.2.9 and 5.2.11 and works in 5.2.5  but the snowflake program works in 5.2.9 and fails in 5.2.4...  The bug is in all of these versions but triggering it is difficult.


I only tested the snowflake program on Ubuntu version 8 using both the standard 5.2.4 and also a self installed 5.2.9 on Ubuntu 8.

Expected result:
----------------
float 0.1 becomes string "0.1"  

or close to it in the case of binary conversion issues.



Actual result:
--------------
The BUG:
 
 The problem is that when php performs thousands of floating point
 operations, at some point corruption occurs and the floating point
 numbers get coerced into an invalid string format.
 
 For example:
 (float) 0.1
 becomes:  (string) (string:4) 0.0:
 
note the colon,  that colon is part of the corruption.  

A floating point number is being turned into a string containing a colon.  How is that possible???
 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-03-26 04:31 UTC] aharvey@php.net
-Status: Open +Status: Feedback
 [2010-03-26 04:31 UTC] aharvey@php.net
It looks like the Web server you've posted the sample code to is
interpreting the PHP files, so it's impossible to get the source.
If you could upload the files with an extension that's not being
handled by your PHP module, that would be handy.

If there's any chance of a more minimal test case, that would also
be rather useful.

Finally, without wanting to sound overly snarky, that description
was about 1200 words too long and infinitely too overwrought.
Brevity is appreciated.
 [2010-03-26 08:51 UTC] codeslinger at compsalot dot com
oops, fixed.

various attempts to isolate this to a simple test case have not yet succeeded.  This program is the closest I've come to a simple test case.

after many hours of working on this, what I can tell you is that it requires lots of calculations and the use of arrays. - lots of memory allocations.

yes, I confess to being overwrought.  I've got 3 years of work, and the future of my software company at stake with this bug. and a lot of experience with bug reports that get ignored, including the original entry for this bug.
 [2010-03-26 08:57 UTC] aharvey@php.net
-Status: Feedback +Status: Assigned -Assigned To: +Assigned To: aharvey
 [2010-03-26 09:30 UTC] pajoye@php.net
-Status: Assigned +Status: Feedback
 [2010-03-26 09:30 UTC] pajoye@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc. If the script requires a 
database to demonstrate the issue, please make sure it creates 
all necessary tables, stored procedures etc.

Please avoid embedding huge scripts into the report.


 [2010-03-26 09:40 UTC] codeslinger at compsalot dot com
did you even LOOOKK  at the script that I provided?

it is not that complicated.  a few loops and some array allocations.
previous attempts to reduce this to anything simpler have been unsuccessful.

this is exactly the attitude that causes me to be overwrought.
 [2010-03-26 09:54 UTC] pajoye@php.net
It looks to me in a bug at the number formatting in the Windows API (not php dependent). Other users met this problem on old XP systems. You could reproduce it using number_format only. Or maybe only with a single printf function.

Can you try using another windows box or using 5.3.2-vc9 builds?

Btw, it is not about bad or good attitude but about having something we can actually use to help you. I can understand your worries after having spent hours to debug this problem, but we will still use a small script to debug this problem, if any.
 [2010-03-26 10:11 UTC] pajoye@php.net
Btw, it could be due to bad initialized data as well (as you experience it on unix as well).

Can you try to run your script under valgrind too?
 [2010-03-26 10:17 UTC] codeslinger at compsalot dot com
Thank You for the response.

This program executes thousands of identical loops
it performs a number format conversion on each of those thousands of numbers in it's array.

Out of all of those thousands of identical conversions about 4 of them will produce an invalid result.

for this specific program, if I skip the array_merge (see $Nest) then the bug does not occur.

Every time I make a change to the loops etc. the behavior changes, even to where the bug is not triggered.  I have already simplified this program quite a bit and the result was that it now fails at a totally different array index then when I first observed the problem.  The trigger is very finicky.

XP is not a factor here, even though the original problem was found on XP, I am running this Snowflake program on Ubuntu Linux.

converting a number to a string should never result in that string containing a non-numeric character.

I can try to reduce this program further, but really and truly, it is hard to trigger this -- but once triggered it is totally consistent and repeatable.
 [2010-03-26 10:23 UTC] codeslinger at compsalot dot com
quote: Btw, it could be due to bad initialized data as well

I don't understand the question/statement.

The program generates all of it's data.

If you look near the bottom of pov.pco.php  you will see the following line:

echo "FATAL ERROR: PHP Math is Corrupt Again!!! idx = $idx\n";

If you set a breakpoint there in a php debugger and examine the vaules you will see that that array contains a float of 0.1
and that the string it was converted to is   "0.0:"
 [2010-03-26 11:11 UTC] codeslinger at compsalot dot com
String conversion errors

There is a flag called $FloatType 
You can use it to select the type of conversion that is done.



//this fails with string conversion error
case 0: $s = (string)$f;    


//this fails with string conversion error
case 12: $s = is_float($f) ? sprintf('%.12F', $f) : (string)$f;   

//this fails with string conversion error
case 14: $s = is_float($f) ? sprintf('%.14F', $f) : (string)$f;   




//this WORKS, does not cause a string conversion error
case 20: $s = is_float($f) ? sprintf('%.20F', $f) : (string)$f;   



When I say conversion error, I mean that the result is "0.0:"  not that php gives any kind of error message.
 [2010-03-26 11:14 UTC] pajoye@php.net
Does it happen always? Can you try to make a script with only this function call with the values causing this effect?
 [2010-03-26 11:17 UTC] aharvey@php.net
-Assigned To: aharvey +Assigned To:
 [2010-03-26 15:28 UTC] codeslinger at compsalot dot com
it's still not 20 lines...  it never will be....  but I found one surprising thing, if I save the array to disk and read it back in I still get the same failure.

so essentially the snowflake is a Psudo-RNG and that's why trying to simplify it does not work, because it has to be able to generate all of those different numbers.  but once we have the set of numbers the generator becomes irrelevant.


Try this program:
http://www.compsalot.com/phpbug/kochsnowflake/simplefail/


weirdly, every failure is a -0.1

but there are two things that I'm concerned about.  

1) It seems unlikely that the billing program was only failing on that amount, it is a pretty unusual amount.  Not one I'd normally expect to see and there were a lot of failures.

2) I'm concerned about the limitations of the detection method.  I am only finding bad values because they have a colon in the string.  I am not currently checking for mathematical correctness.  We may not be seeing the whole story, there could be a lot more bad values that just are not blatant enough to be observed.


But at least this should give you the starting point that you are asking for.  The program is reduced to reading a file from disk and checking each number to see if it's valid.  can't get any simpler than that.  

Of course if the corruption is happening when the value is created, looking at them after the fact may still not help much.  But when I look at these values in the eclipse zend debugger, they look normal enough despite the fact that they can't be properly converted.


------------------------------
The data files are as follows:

rawpairs.txt  is a 6.5meg file and contains both good and bad values, you don't need this file unless you are trying to validate the serialization.  This is from a single run of the snowflake, $Nest = 3; $Depth = 5;

The following were extracted from the raw data.
onepair.txt  contains a single failure item

selectpairs.txt  contains 8 failures which were from a single run of snowflake

manypairs.txt   contains about 40 failures which are the result of multiple runs of the snowflake using different Nest & Depth parameters.
 [2010-03-26 16:26 UTC] rasmus@php.net
I ran your simplefail.php on all 4 data files.  Never saw the failure case.  
Then I took just the huge rawpairs.txt file (had to increase the memory_limit) 
and modified your program slightly to do:

for($i=0;$i<100000;$i++) ConvertData($data);

and ran that, which took quite a while.  Still no failures.

You are still the only person who has ever reported these weird ":" characters 
showing up, and you have yet to produce any sort of code that reproduces it for 
someone else.  We'll keep trying, but something that happens for 1 person out of 
millions is suspicious.
 [2010-03-26 16:39 UTC] pajoye@php.net
Rasmus, he is not the only person. There are two other reports about it. However he is the first one to experience it on non windows platform.
 [2010-03-26 16:57 UTC] aharvey@php.net
JFTR, I was also unable to reproduce the failure case from any of the data files on both 32-bit and 64-bit Linux builds and a 32-bit Windows build. I've got a couple of boxen crunching away generating random doubles and converting them to strings in what seems to be the sort of range that causes problems (one 32-bit Linux, one 64-bit Linux): nothing yet after a couple of billion iterations.

In short, I don't have a clue what it could be either, but I'll keep the random double generation going a while longer just in case it hits paydirt.
 [2010-03-26 17:18 UTC] rasmus@php.net
Bad memory perhaps?  But why consistently a ':' ?
 [2010-03-26 17:25 UTC] aharvey@php.net
Well, it is the next character after '9', and the character string is built up in zend_dtoa() by adding a value L (presumably intended to be in the range 0..9) to '0'. If L somehow ends up being 10, you'd get a colon.

With the values that are apparently causing problems (the problematic value in onepair.txt is 0.09999999999999999167...), it does kind of look like a rounding issue to me, although I've no idea why it's not being triggered by more than two or three users in that case.
 [2010-03-26 21:02 UTC] codeslinger at compsalot dot com
The billing program was failing on multiple computers at multiple locations, it failed on XP and Windows 2000 with various cpus. Those were customer sites!  I reproduced the problem on a vmware setup with windows 2000.

This snowflake program is failing on Ubuntu Hardy 8.0.4 with all of the updates.  This is the stock php that comes with Ubuntu. This is a Pentium M 32bit Laptop.  I've never experienced a memory error on this computer and the fact of it's consistency would argue against this being some kind of hardware issue.

Here is what I get when I run the simplefail in the default config.

php -v
PHP 5.2.4-2ubuntu5.10 with Suhosin-Patch 0.9.6.2 (cli) (built: Jan  6 2010 22:01:14) 
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
    with Xdebug v2.0.3, Copyright (c) 2002-2007, by Derick Rethans
    with Zend Debugger v5.2.15, Copyright (c) 1999-2008, by Zend Technologies

==========

php simplefail.php

Selected onepair.txt, Found 1 items

(string)(double) -0.1 === -0.1  which of course is correct
But when we convert the value in an array it fails

Conversion Error: PHP Math  idx = 0 || '-0.1'  !== '-0.0:'


=====

THANK YOU  I REALLY APPRECIATE THE HELP
 [2010-03-26 21:32 UTC] codeslinger at compsalot dot com
as far as the low incidence of occurrence and the millions of users not seeing it.

I've said all along that it is hard to reproduce.  But when dealing with financial transactions, that is not good enough, it only takes one mistake to have a huge problem on your hands.

Out of all of those millions of users, I'd venture to say that the very overwhelming majority are using php for string processing not number crunching.  And in many cases where it does show up such as positioning something on a web page, it would be easy to shrug off.  So there is no way to know how often this happens in the wild, based on user feedback.
 [2010-03-26 21:37 UTC] pajoye@php.net
Please try using this snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/


 [2010-03-27 12:22 UTC] codeslinger at compsalot dot com
well, it's hard to prove a negative.

but I have run a bunch of tests on the Linux snapshot and it appears to be working fine.  A VERY BIG THANKYOU

I did not find any windows snapshots, the latest is 5.2.13 from Feb 24.

based on the symptoms, my initial assumption was that this was caused by some kind of array corruption, this turned out to be wrong.  the actual repro can be boiled down to one line...  :-)

echo (string) (double) -0.09999999999999999;


With the caveat that there are other values which also trigger this.
 [2010-03-27 12:50 UTC] codeslinger at compsalot dot com
One further note, in the repro above, it has to be exactly 16 nines.  by adding or removing a 9, it does not fail.

Also, as far as I know, all of the failures have been on 32bit Intel cpu's.  This probably will not fail on a 64bit cpu.
 [2010-03-27 14:19 UTC] johannes@php.net
You are mentioned this version information:

php -v
PHP 5.2.4-2ubuntu5.10 with Suhosin-Patch 0.9.6.2 (cli) (built: Jan  6
2010 22:01:14) 
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
    with Xdebug v2.0.3, Copyright (c) 2002-2007, by Derick Rethans
    with Zend Debugger v5.2.15, Copyright (c) 1999-2008, by Zend
Technologies

This version is very different from the versions we provide.
a) Ubuntu adds some custom patches
b) Suhosin does major changes to the engine
c) Xdebug as well as Zend Debugger do changes to our executor unit.

All these components aren't supported here.
 [2010-04-13 03:36 UTC] john dot smith dot 1964 at gmail dot com
I am seeing this bug consistently on standard Windows builds such as 5.2.4 and 
5.2.13.

Our Server is: Windows NT 5.2 build 3790

Sample code is simple:

<? echo round(1451,2); ?>

On 5.2.4 it will result in "1450.:0" every time. On 5.2.4, other such *funny* 
values are 
1701,1821,1951,2091,2101,2111,2121,2341,2351...

On 5.2.13,the numbers 1700 and 1900 consistently return "colon-ized" results. 
This is a 
especially problematic, because 1700 and 1900 occur more frequently in our 
eCommerce app!

This issue is a real problem for us. It has been touched on (but not solved) in 
at least 
Bugs 46376, 47716, 47304 and 47418.
 [2010-04-14 04:37 UTC] john dot smith dot 1964 at gmail dot com
The folk at Mandriva saw the same problem, figured it out and submitted a patch to   
PHP. I'm confused, because we're certainly still seeing the problem:

https://qa.mandriva.com/show_bug.cgi?id=37171

"In PHP on Mandriva 2008, some float to string conversions return "0.0:" !!
In critical software, this can lead to major loss of data or inconsistant
results."
 [2010-05-23 09:38 UTC] codeslinger at compsalot dot com
In response to johannes@php.net  above.....

Let me just very politely reiterate that I originally encountered this bug on the STOCK WINDOWS BUILD from php.net,  therefore to dismiss this bug because it is ubuntu specific is not a valid reason.

This bug is very hard to reproduce, but none-the-less occurs far too frequently under real-world conditions.

The actual values required to reproduce this bug appear to vary depending on what version of php is being tested and what os/cpu it is running on.

Given the randomly variant nature of this problem, I suspect that the only way you could properly test this bug and have confidence in the outcome is if you loop through every possible floating point value and convert it to a string.  You would also need to do this on multiple platforms. Of course that would probably take a few years...   so perhaps code inspection and some alerts would be a better option.  Testing numbers selected at random is not likely to succeed, the number space is too large and you can't account for possible biases in the random number generator -- perhaps it only returns numbers which php sees as valid.

Other people have reported this bug, see for instance #49764  and also the above comments about Mandriva Devs creating a patch to fix this bug.

I do not regard millions of Ubuntu users as unimportant, or irrelevant.  The severity of the consequences of this bug ought to be sufficient justification for a little bit of extra effort being expended -- even if the problem had been caused by ubuntu patches which it wasn't.  

People who are affected by this bug may not always realize what the problem is.  This bug is probably underreported by quite a bit.  Also as pointed out earlier the majority of php web pages do not do very much floating point math and therefore would not encounter this bug.

In the discussion above it appears that there is some obscure case for which the number conversion is off-by-one.  Pajoye thinks he has a fix.


The fact that this afflicts Financial Transactions -- as reported by multiple people -- makes this a gravely serious bug...   so why then is it so exasperatingly difficult to get the php dev community to take this problem seriously?


In case you are wondering why it took me so long to respond to Johannes, it's because I had to cool off first....  I really am trying not to be overwrought, honest, ;-)
 [2010-05-23 14:42 UTC] pajoye@php.net
There is no need to write a novel about this possible issue.

Please ask the Mandriva guys to actually report a bug here (in this report for example), post their patch(es), a reproduce script with a description of their architecture (compiler, compiler versions, OS, etc.).

Everything else are unnecessary information.

Now, what Johannes said is still valid:
- we don't support custom version of PHP (aka patched)
 - that includes suhoshin patch
- Debugger/optimizer (zend, xdebug, etc.) has to be removed to reproduce a problem.

Thanks for your feedback.
 [2010-05-24 02:04 UTC] codeslinger at compsalot dot com
Yipee!!!  at least I have finally found a work-around that I can live with!!!
You can close this bug now.


The Mandriva Devs seem to think that this is actually a GCC bug and that it is Dependant on the build flags used.  You can read about it here.   https://qa.mandriva.com/show_bug.cgi?id=37171
Thanks to John (above) for the link.


A lot more reading/searching of this WELL KNOWN ISSUE  finally lead me to here:  

http://www.mysqlperformanceblog.com/2008/01/10/php-vs-bigint-vs-float-conversion-caveat/

and here:
http://www.farad.com.au/source_code/php/setting_floating_point_precision_src.php


To cut to the chase, the actual work-around is to change the "precision".  This solution was hinted at by my simplefail.php program (test option 20), but I was unaware of an ini setting that is available for this.

The solution to all of this madness and it is very mad indeed...   is to add the following in your php program.  

ini_set("precision", 16);


End of Problem.... End of Bug...

Like Good Day Eh?
 [2010-05-24 02:18 UTC] pajoye@php.net
-Status: Feedback +Status: Bogus
 [2010-05-24 02:18 UTC] pajoye@php.net
.
 [2010-05-24 03:17 UTC] john dot smith dot 1964 at gmail dot com
This problem isn't fixed for us by adding "ini_set("precision", 16);". Our PHP 
install is stock off the website (5.2.4 and 5.2.13, for instance) and our box runs 
Windows 2003.
 [2010-05-24 13:46 UTC] codeslinger at compsalot dot com
In Summary:  As Reported by Multiple People

Windows XP (32 bit)  PHP 5.2.4  Fails
Windows XP (32 bit)  PHP 5.2.5  Works
Windows 2000 (32 bit)  PHP 5.2.5  Works
Windows XP (32 bit)  PHP 5.2.9  Fails
Windows 2000 (32 bit)  PHP 5.2.9  Fails
Windows 2000 (32 bit)  PHP 5.2.11 Fails
Windows 2003 (?? bit)  PHP 5.2.12 Fails
Windows 2003 (?? bit)  PHP 5.2.13 Fails

Ubuntu 8 (32bit)  PHP 5.2.4  Fails
Ubuntu 8 (32bit)  PHP 5.2.9 (custom build)  Works
Ubuntu 9 (64bit)  PHP 5.2.10  Works

Mandriva 2008 (32bit & 64bit)  PHP 5.2.4 Works
Mandriva 2008 (32bit & 64bit)  Unpatched PHP 5.2.5 Fails

This bug has been reported by multiple people.  The above list is the combination of my own testing plus what I found reported by other people.  The windows oses are all using the STOCK BUILD as provided by php.net


It is very important to understand that the specific values which fail are highly variable.  A specific value which fails on one os/php version does not necessarily fail on a different combination of os+php, but a different value will fail instead.

It is also important to realize that given the obscurity and variability of this bug, just because a particular version of php is reported as working, does not guarantee that the bug does not exist, it only says that so far no one has reported encountering a specific value which triggers this bug.

All of the following are thought to influence the specific behavior and reproducibility of this bug.

The number of cpu bits
The operating system
The specific version of php
The compiler flags that were used to build php
The "precision" setting for php
The format specifier/precision in an sprintf statement
sprintf versus implied (string) conversion

It is also possible that the floating point hardware could have an influence on the reproducibility of this bug.

Since the WORK-AROUND did not work for John, it would appear that we still have a problem which needs to be solved.
 [2010-05-24 13:59 UTC] pajoye@php.net
Please read my last comment and provide the info I asked there. Without that, there is not a chance to get anywhere regarding this issue.
 [2010-05-24 14:04 UTC] codeslinger at compsalot dot com
P.S.  Please note that in my own testing I have verified that the presence or absence of the xdebug and zend debug extensions do not alter the behavior of this bug, this was verified on Windows.

Also note how for instance 5.2.4 fails on Windows and on Ubuntu but works on Mandriva  (or at least was not found to fail on Mandriva).

Also I can tell you from my own testing that the specific values which fail on Windows are very different from the specific values which fail on Unbuntu, when tested on the same computer.  The only thing which can be said with some level of confidence is that all of the failures involve numbers with the digit 9 in them.  Since these are 58? digit numbers and only a very few specific values fail, the potential to NOT see a failure is huge.
 [2010-05-24 14:14 UTC] pajoye@php.net
And please use latest 5.3 or 5.2, from our downloads (only).
 [2010-05-24 14:29 UTC] codeslinger at compsalot dot com
Pajoye
Please take a look at #43487   this appears to be where the Mandriva Devs landed their change.

Quote:
"as peroyvind found, the miscompilation is inside Zend/zend_strtod.c,
and -no-ftree-vrp workaround the bug."


Unfortunately that change does not appear to have done the trick.  This thing is dang hard to reproduce, short of running through every possible 58 digit number, or getting really lucky with random numbers, I can't see how to reliably test this.
 [2016-06-12 04:28 UTC] sandino at sandino dot net
<?php

ini_set("precision",16);
echo (string) (double) -0.09;
echo "\n";
echo (string) (double) -0.099;
echo "\n";
echo (string) (double) -0.0999;
echo "\n";
echo (string) (double) -0.09999;
echo "\n";
echo (string) (double) -0.099999;
echo "\n";
echo (string) (double) -0.0999999;
echo "\n";
echo (string) (double) -0.09999999;
echo "\n";
echo (string) (double) -0.099999999;
echo "\n";
echo (string) (double) -0.0999999999;
echo "\n";
echo (string) (double) -0.09999999999;
echo "\n";
echo (string) (double) -0.099999999999;
echo "\n";
echo (string) (double) -0.0999999999999;
echo "\n";
echo (string) (double) -0.09999999999999;
echo "\n";
echo (string) (double) -0.099999999999999;
echo "\n";
echo (string) (double) -0.0999999999999999;
echo "\n";
echo (string) (double) -0.09999999999999999;
echo "\n";
echo (string) (double) -0.099999999999999999;
echo "\n";
echo (string) (double) -0.0999999999999999999;
echo "\n";
echo (string) (double) -0.09999999999999999999;
echo "\n";
echo (string) (double) -0.099999999999999999999;
echo "\n";
echo (string) (double) -0.0999999999999999999999;
echo "\n";

/* Seems like something is still broken:
php test.php 

-0.09
-0.099
-0.0999
-0.09999
-0.099999
-0.0999999
-0.09999999
-0.09999999900000001
-0.0999999999
-0.09999999999
-0.099999999999
-0.0999999999999
-0.09999999999999
-0.09999999999999901
-0.09999999999999989
-0.09999999999999999
-0.1
-0.1
-0.1
-0.1
-0.1
*/
?>
 [2016-06-12 04:32 UTC] sandino at sandino dot net
<?php

/* This one is better */
ini_set("precision",17); /* changed precision from 16 to 17 */

echo (string) (double) -0.09;
echo "\n";
echo (string) (double) -0.099;
echo "\n";
echo (string) (double) -0.0999;
echo "\n";
echo (string) (double) -0.09999;
echo "\n";
echo (string) (double) -0.099999;
echo "\n";
echo (string) (double) -0.0999999;
echo "\n";
echo (string) (double) -0.09999999;
echo "\n";
echo (string) (double) -0.099999999;
echo "\n";
echo (string) (double) -0.0999999999;
echo "\n";
echo (string) (double) -0.09999999999;
echo "\n";
echo (string) (double) -0.099999999999;
echo "\n";
echo (string) (double) -0.0999999999999;
echo "\n";
echo (string) (double) -0.09999999999999;
echo "\n";
echo (string) (double) -0.099999999999999;
echo "\n";
echo (string) (double) -0.0999999999999999;
echo "\n";
echo (string) (double) -0.09999999999999999;
echo "\n";
echo (string) (double) -0.099999999999999999;
echo "\n";
echo (string) (double) -0.0999999999999999999;
echo "\n";
echo (string) (double) -0.09999999999999999999;
echo "\n";
echo (string) (double) -0.099999999999999999999;
echo "\n";
echo (string) (double) -0.0999999999999999999999;
echo "\n";

/* Seems like something is still broken:
php --version
PHP 5.5.35-pl0-gentoo (cli) (built: May 13 2016 22:17:08) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

php test.php 
-0.089999999999999997
-0.099000000000000005
-0.099900000000000003
-0.099989999999999996
-0.099999000000000005
-0.099999900000000003
-0.099999989999999997
-0.099999999000000006
-0.099999999899999997
-0.099999999990000005
-0.099999999999
-0.099999999999900002
-0.09999999999999
-0.099999999999999006
-0.099999999999999895
-0.099999999999999992
-0.10000000000000001
-0.10000000000000001
-0.10000000000000001
-0.10000000000000001
-0.10000000000000001
*/
?>
 [2016-06-12 06:34 UTC] requinix@php.net
@sandino: That's not the original bug, nor is it a bug at all. It's the unfortunate nature of floating-point numbers. http://www.floating-point-gui.de/
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 21:01:36 2024 UTC