Page 1 of 1
serialize and floats
Posted: Sun Feb 01, 2009 4:47 pm
by s.dot
Code:
Code: Select all
$out['assigned'] = round($assignedSumArr['assigned'], 2);
$out['unassigned'] = round($unassignedSumArr['unassigned'], 2);
print_r($out);
Result:
Code: Select all
Array
(
[assigned] => 349720.02
[unassigned] => 5313.93
)
Continuing the code:
Code: Select all
$out = serialize($out);
echo $out;
Result:
Code: Select all
a:2:{s:8:"assigned";d:349720.0200000000186264514923095703125;s:10:"unassigned";d:5313.9300000000002910383045673370361328125;}
Why is serialize() turning my round()'d numbers back into loooong floats!?
Re: serialize and floats
Posted: Sun Feb 01, 2009 5:08 pm
by VladSun
Probably because of the format of float - I think you can't have an exact value of 349720.02 - floats are always presented with some precision error.
You need a fixed point format, IMHO. That is - serialize the float as integer multiplied by 100, and when you unserialize - divide by 100. So you have a fixed point format - Y.XX
Re: serialize and floats
Posted: Sun Feb 01, 2009 5:10 pm
by requinix
For a lot of numbers the
floating-point format does not precisely describe the number. It gets close but not exact.
0.02 is 1/50 is 1/64 + 1/256 + 1/1024 + 1/4096 + 1/4194304 +... Each denominator is a power of two, and that restriction means the series won't end. No exact representation.
There's a php.ini setting. Not quite sure how it's used because it doesn't seem to work as I expect.
Code: Select all
; When floats & doubles are serialized store serialize_precision significant
; digits after the floating point. The default value ensures that when floats
; are decoded with unserialize, the data will remain the same.
serialize_precision = 100
Anyways, that's the problem: PHP is storing all the data it has so that the unserialized number is as "accurate" as possible.
Code: Select all
$var = 0.02;
echo serialize($var); // windows 7 x64
// d:0.0200000000000000004163336342344337026588618755340576171875;
ini_set("serialize_precision", ini_get("precision"));
echo serialize($var);
// d:0.02;
Re: serialize and floats
Posted: Sun Feb 01, 2009 5:12 pm
by VladSun
Nice explanation, tasairis.
I've never known about
serialize_precision param

Thanx
Re: serialize and floats
Posted: Sun Feb 01, 2009 5:22 pm
by Benjamin
Floats are Floats, typecast them to strings before you serialize them, that should fix it.
Re: serialize and floats
Posted: Sun Feb 01, 2009 5:25 pm
by s.dot
Thanks guys.
Code: Select all
$out['assigned'] = (string) round($assignedSumArr['assigned'], 2);
That fixed it, thanks astions.
This particular feature is a bit inconvenient. I thought rounding two two places (even if it was a float) would be two places, period. I guess I can understand it though.