#23298 [Ver]: Floating point data loss in serialize() (and sessions)
| From: | sniper@php.net | Date: | Fri, 25 Apr 2003 15:52:05 +0000 |
| Subject: | #23298 [Ver]: Floating point data loss in serialize() (and sessions) | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-38374@lists.php.net to get a copy of this message | ||
ID: 23298
Updated by: sniper@php.net
Reported By: swbrown at ucsd dot edu
Status: Verified
-Bug Type: Variables related
+Bug Type: Scripting Engine problem
Operating System: any
PHP Version: 4.3.2-RC
New Comment:
Here's another test script:
<?php
ini_set("precision", 32);
$var = 1.0 / 0.7;
echo "float($var)\n";
var_dump($var);
?>
Output:
-------
float(1.4285714285714286031492292750045)
float(1.4285714285714286475581502600107)
This all is most likely related to the serialize()
bug too.
Previous Comments:
------------------------------------------------------------------------
[2003-04-23 11:48:34] sniper@php.net
Forgot the output:
# php test.php
float(1.4285714285714286475581502600107)
d:1.4285714285714286031492292750045;
float(1.4285714285714286475581502600107)
bool(true)
float(1.42857142857)
d:1.42857142857;
float(1.42857142857)
bool(false)
(notice the difference in the value in first part..)
------------------------------------------------------------------------
[2003-04-23 11:47:27] sniper@php.net
php.ini option 'precision', when set high enough will let
this work as expected. (precision=18)
Here's a bit better example script that shows the problem:
<?php
ini_set("precision", 32);
$var = 1.4285714285714286476;
var_dump($var);
$foo = serialize($var);
echo ' ', $foo, "\n";
$x = unserialize($foo);
var_dump($x);
var_dump($x === $var);
ini_set("precision", 12);
$var = 1.4285714285714286476;
var_dump($var);
$foo = serialize($var);
echo ' ', $foo, "\n";
$x = unserialize($foo);
var_dump($x);
var_dump($x === $var);
?>
------------------------------------------------------------------------
[2003-04-21 15:22:45] swbrown at ucsd dot edu
I ran into a bug in my code where the floating point number I put in a
session variable changed slightly when it was loaded from the session
the next time around, which in this case caused some math to differ by
1 depending on if the object had been through a session before. This
was definately not expected behavior, as I would expect data to be
invariant under serialization. I poked around at this for a bit, and
I'm guessing that PHP uses serialize() to serialize session variables,
and serialize() has data loss issues with float/double as it tries to
convert them into truncated base 10 numbers.
Test case:
<?php
$var = 1.0 / 7.0;
$x = unserialize(serialize($var));
if($x != $var) print("FAIL\n");
else print("SUCCESS\n");
?>
One way I think this could be fixed is to add a new serialize field
type other than 'd' for serialize()ing floats/doubles so that future
PHP releases can serialize the entire float in base 16 or something so
it won't alter data and won't break BC. Maybe 'e' for IEEE or
something. Serialization should never alter the data being serialized,
or it creates all sorts of funky problems (like mine where the object
acts slightly different depending on if it's gone through a session).
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=23298&edit=1