11 php random floating-point serialization
我在6到8之间生成10个随机浮点数(完全有理由),并以序列化形式将它们写入mysql数据库.但是在存储时似乎出现了一个怪癖:
在存储之前我只是输出相同的数据来查看它的样子,这就是我得到的结果
a:10:{i:0;d:6.20000000000000017763568394002504646778106689453125;i:1;d:7.5999999999999996447286321199499070644378662109375;i:2;d:6.4000000000000003552713678800500929355621337890625;..}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我得到的数字很长,比如6.20000000000000017763568394002504646778106689453125而不是我真正想看到的,只有6.2.只有在我序列化数据时才会发生这种情况,如果我只是输出数组,我确实将浮点值设置为一位小数.这是我的代码:
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);
Run Code Online (Sandbox Code Playgroud)
Joe*_*oey 16
在计算机中使用浮点数学不能准确表示像6.2那样的数字,因为它没有有限的基数2表示.你看到echo的是什么 - 数字是用于人类阅读的东西,因此值将四舍五入到浮点数可以提供的准确度(32位为6位小数,64位FP值为17位).
但是,在序列化这些值时,您确实需要精确值(即其中的所有位)而不仅仅是最接近的"nice"值.可能有一个以上的浮点/双精度表示,其计算结果为约6.2和序列化时,你通常真的想要存储他确切值,你才能正确地恢复它们拥有的是最后一位.这就是为什么你在那里的价值观中获得荒谬的"准确性".这一切只是为了保留您开始使用的确切位表示.
但是,为什么要严格控制序列化输出呢?我的意思是,它只是在那里,所以你可以往返数据结构,并在以后读取它.你当然不希望在输出中的某个地方使用那个序列化表示给人类.因此,如果它只是"漂亮"的值,则不应使用具有完全不同目的的序列化.
使用number_format后将它们存储为字符串:
$number = number_format($float, 2);
Run Code Online (Sandbox Code Playgroud)