PHP 中的浮点数 -- 奇怪的行为 [重复]

Floating point numbers in PHP -- strange behaviour [duplicate]

提问人:user1442439 提问时间:11/20/2020 更新时间:11/20/2020 访问量:633

问:

有人可以解释一下这里发生了什么吗?我有四舍五入到小数点后两位(价格)的浮点数。

echo $total . " is rounded to " . round((float)$total,2);
var_export((float)$total);
echo " is rounded to ";
var_export(round((float)$total,2));
echo "\r\n";

输出为: 79.95 四舍五入为 79.95 79.9500000000000028421709430404007434844970703125 四舍五入为 79.9500000000000028421709430404007434844970703125

因此,“回声”会自行完成。当我使用 var_export() 输出数据时,似乎 round() 不起作用。

只是为了测试,我做了:

$total = 79.9501234576908988888;

然后我得到: 79.950123457691 四舍五入为 79.95 79.9501234576908927920158021152019500732421875 四舍五入为 79.9500000000000028421709430404007434844970703125

因此,“echo”似乎会自动将浮点数四舍五入到小数点后 11 位。为什么 round() 不适用于 var_export 是一个谜。

有人有解释吗?

谢谢

鲁道夫

php 点浮 点精度

评论

0赞 jspit 11/20/2020
您使用的是哪个 PHP 版本。还是 PHP 5.x?

答:

1赞 Ken Lee 11/20/2020 #1

浮点数具有特定的有限精度。虽然这取决于系统,但 PHP 通常使用 IEEE 754 双精度格式,由于四舍五入,该格式将产生最大的相对误差,顺序为 1.11e-16。

在本例中,如果您使用 var_export,它将输出(或返回)变量的可解析字符串表示形式,在这种情况下,当您的数据存储为浮点变量时,该字符串表示形式也将返回所有数据。

这就是为什么当您执行以下命令时

var_export(round((float)$total,2));

系统首先将$total四舍五入为 79.95,但由于您指定了浮点转换,因此它会将其存储为系统的数据精度,因此当您使用var_export忠实地返回数据时,它会为您提供类似

79.9500000000000028421709430404007434844970703125

另一方面,PHP var_export 函数足够智能,可以区分您尝试解析的数据类型。(即使您不使用浮动转换)。因此,如果您解析“79”,该值将被视为整数,如果您解析“79.123”,该值将被视为浮点数。

说出以下代码:

<?php
//$total = 79.9501234576908988888;
$total = 79;

echo "parsing 79";
echo "<br>";

var_export((float)$total);
echo " is rounded to ";
var_export(round((float)$total,2));
echo "<br><br>";

$total = 79.123;

echo "parsing 79.123";
echo "<br>";


var_export($total);
echo " is rounded to ";
var_export(round($total,2));
echo "<br><br>";



?>

结果将是:

解析 79

79 四舍五入为 79

解析 79.123

79.12300000000000046611603465862572193145751953125 四舍五入为 79.1200000000000045474735088646411895751953125

评论

0赞 user1442439 11/20/2020
嗯。。但是我在四舍五入之前投射到浮动,所以真的应该得到 79.95000000000000000000。此外,省略对浮点的强制转换不会更改行为。
0赞 Ken Lee 11/20/2020
我稍后会给你更多的信息。
0赞 Ken Lee 11/20/2020
对不起,我在地铁里,所以我需要时间写一个更详细的解释。请看我修改后的答案
0赞 user1442439 11/20/2020
谢谢你的解释。我做了矿石阅读和测试。INI 设置“serialize_precision”是导致该行为的原因。所以现在我知道为什么它会以这种方式发生,我可以修复系统,使其正常工作。(不,我不打算改变设置,但它对理解问题至关重要)
0赞 Ken Lee 11/20/2020
是的,在我的理解中,这是 许多服务器中使用的默认精度 ,但如果您愿意,可以覆盖它。很高兴知道您已经进入了下一个级别。快乐编码兄弟!
0赞 jspit 11/20/2020 #2

var_export () 的舍入方式取决于 PHP 版本和系统设置“serialize_precision”。您可以使用以下方式显示设置:

var_dump(ini_get('serialize_precision'));

如果您的权利允许,您可以

ini_set('serialize_precision',"-1");

改变这个。“-1”表示将使用增强算法对此类数字进行四舍五入。

该指令必须始终位于脚本的开头,或者您可以更改 php.ini 中的设置。

评论

0赞 user1442439 11/20/2020
是的,谢谢。我不知道这个设置。现在,我做了更多的阅读,并玩了:p概念屋顶“的设置,这一切都是有道理的