提问人:user1442439 提问时间:11/20/2020 更新时间:11/20/2020 访问量:633
PHP 中的浮点数 -- 奇怪的行为 [重复]
Floating point numbers in PHP -- strange behaviour [duplicate]
问:
有人可以解释一下这里发生了什么吗?我有四舍五入到小数点后两位(价格)的浮点数。
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 通常使用 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
评论
var_export () 的舍入方式取决于 PHP 版本和系统设置“serialize_precision”。您可以使用以下方式显示设置:
var_dump(ini_get('serialize_precision'));
如果您的权利允许,您可以
ini_set('serialize_precision',"-1");
改变这个。“-1”表示将使用增强算法对此类数字进行四舍五入。
该指令必须始终位于脚本的开头,或者您可以更改 php.ini 中的设置。
评论