serialize and floats

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

serialize and floats

Post 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!?
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Re: serialize and floats

Post 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
Last edited by VladSun on Sun Feb 01, 2009 5:11 pm, edited 1 time in total.
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: serialize and floats

Post 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;
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Re: serialize and floats

Post by VladSun »

Nice explanation, tasairis.
I've never known about serialize_precision param :) Thanx
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: serialize and floats

Post by Benjamin »

Floats are Floats, typecast them to strings before you serialize them, that should fix it.
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Re: serialize and floats

Post 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.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
Post Reply