PHP - 序列化浮点数 [英] PHP - Serialize floating points

查看:320
本文介绍了PHP - 序列化浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在6到8之间生成了10个随机的浮点数(所有的原因都是这样的),然后把它们以序列化的形式写入mysql数据库。但在存储时间似乎出现了一个怪癖:

在存储之前,我只是输出相同的数据,看看它是什么样子,这是我得到的结果

  A:10:{I:0; d:6.20000000000000017763568394002504646778106689453125; I:1; d:7.5999999999999996447286321199499070644378662109375; I:2; d :6.4000000000000003552713678800500929355621337890625; ..} 

正如你所看到的,我越来越长的数字像6.20000000000000017763568394002504646778106689453125
,而不是我真正想要看到的,只有6.2。这只是当我序列化的数据,如果我只是输出数组,我得到浮点数到一位小数。
这是我的代码:

 函数random_float($分钟,$最大){
返回($分钟+ lcg_value()*(ABS($ $ MAX- MIN)));
}

$ a1 = random_float(6,8);
$ a1 = round($ a1,1);
$ a2 = random_float(6,8);
$ a2 = round($ a2,1);
$ a3 = random_float(6,8);
$ a3 = round($ a3,1);
...
$ array = array($ a1,$ a2,$ a3,$ a4,$ a5,$ a6,$ a7,$ a8,$ a9,$ a10);

echo serialize($ array);


解决方案

计算机中的浮点数学,因为它没有有限的基数2表示。你看到什么时候 echo - 这个数字是用于人类阅读的东西,因此这个数值将被四舍五入到浮点数可以提供的准确度(小数点后6位32位和17位的64位FP值)。

然而,当序列化这些值时,你确实需要确切的值(即所有位在那里)而不仅仅是最近的好价值。可能有多个浮点/双精度表达式计算大约为6.2,并且在序列化时,您通常真正希望将精确值存储到最后一位,以便正确恢复它们。这就是为什么你在那里的价值观中变得荒谬的准确性。这只是为了保留你开始的确切位表示。



但是,为什么你要严格控制序列化的输出呢?我的意思是,它只是在那里,所以你可以绕过你的数据结构,并在以后读回来。你当然不希望在输出的某个地方使用那个序列化的表示。所以,如果只是好看的值,你不应该使用具有完全不同目的的序列化。


I am generating 10 random floats between 6 and 8 (all for good reason), and writing them to a mysql database in a serialized form. But one quirk seems to emerge at the storage time:

Before storing I'm just outputting the same data to see what it looks like, and this is the result I get

a:10:{i:0;d:6.20000000000000017763568394002504646778106689453125;i:1;d:7.5999999999999996447286321199499070644378662109375;i:2;d:6.4000000000000003552713678800500929355621337890625;..}

As you can see, I'm getting long numbers like 6.20000000000000017763568394002504646778106689453125 instead of what I'd really to like see, just 6.2. This is happening only when I serialize the data, if I just output the array, I do get the floats to one decimal. Here is my code:

function random_float ($min,$max) {
   return ($min+lcg_value()*(abs($max-$min)));
}

$a1 = random_float(6, 8);
$a1 = round($a1, 1);
$a2 = random_float(6, 8);
$a2 = round($a2, 1);    
$a3 = random_float(6, 8);
$a3 = round($a3, 1);
    ...
$array = array($a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10);

echo serialize($array);

解决方案

A number like 6.2 can't be represented exactly using floating-point math in computers as there is no finite base-2 representation of it. What you are seeing when echo-ing the number is something intended for human reading, and thus the value will be rounded to what floats can provide in accuracy (about 6 decimal places for 32-bit and 17 for 64-bit FP values).

When serializing those values, however, you really want the exact value (i. e. all bits that are in there) and not just the nearest "nice" value. There could be more than one float/double representation which evaluates to approximately 6.2 and when serializing you usually really want to store he exact values to the last bit you are having in order to restore them correctly. That's why you're getting ridiculous "accuracy" in values there. It's all just to preserve the exact bit representation of what you started with.

But why exactly do you want to control the serialized output that tightly? I mean, it's just there so you can round-trip your data structure and read it back in later. You certainly don't want to use that serialized representation somewhere in output for humans or so. So if it's just about "nice-looking" values, you shouldn't use serialize which has an entirely different purpose.

这篇关于PHP - 序列化浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆