PHP中的浮点数--奇怪的行为
有人能解释一下这里发生了什么吗?我有一个浮点数,要四舍五入到两个小数点(价格) 输出为: 79.95四舍五入为79.95 79.9500000000000028421709430404007434844970703125四舍五入为79.95000000284217094304040074348449703125 所以,“回声”会自动循环。当我使用var_export()输出数据时,round()似乎不起作用 为了测试,我做了:PHP中的浮点数--奇怪的行为,php,floating-point,floating-accuracy,Php,Floating Point,Floating Accuracy,有人能解释一下这里发生了什么吗?我有一个浮点数,要四舍五入到两个小数点(价格) 输出为: 79.95四舍五入为79.95 79.9500000000000028421709430404007434844970703125四舍五入为79.95000000284217094304040074348449703125 所以,“回声”会自动循环。当我使用var_export()输出数据时,round()似乎不起作用 为了测试,我做了: $total = 79.9501234576908988888;
$total = 79.9501234576908988888;
然后我得到:
79.950123457691四舍五入为79.95
79.9501234576908927920158021152019500732421875四舍五入为79.9500000000000028421709430404007434844970703125
所以,“echo”似乎会自动将浮点舍入到11个小数点。为什么round()不使用var_导出是个谜
有人有解释吗
谢谢
鲁道夫浮点数具有特定的、有限的精度。尽管取决于系统,PHP通常使用IEEE 754双精度格式,由于舍入的顺序为1.11e-16,因此会产生最大相对误差 在本例中,如果使用var_export,它将输出(或返回)变量的可解析字符串表示形式,在本例中,当您的数据存储为浮点变量时,它还将返回所有数据 这就是为什么当您执行以下命令时
var_export(round((float)$total,2));
系统将首先将$total四舍五入到79.95,但是由于您指定了float cast,它将存储到系统的数据精度,因此当您使用var_导出忠实地返回数据时,它将为您提供如下信息
79.9500000000000028421709430404007434844970703125
另一方面,PHP var_导出函数足够智能,可以区分您试图解析的数据类型。(即使不使用浮动铸造)。因此,如果解析“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.123000000000046611603465862572193145751953125四舍五入为79.120000000000004547350886411895751953125变量导出()的四舍五入方式取决于PHP版本和系统设置“序列化精度”。您可以通过以下方式显示设置:
var_dump(ini_get('serialize_precision'));
如果你的权利允许,你可以
ini_set('serialize_precision',"-1");
改变这个。“-1”表示将使用改进的算法对这些数字进行四舍五入
指令必须始终位于脚本的开头,或者您可以在php.ini中更改设置。Hmm。。但我在四舍五入之前先进行浮点运算,所以应该得到79.9500000000000000000。另外,省略cast to float不会改变行为。稍后我会给你更多信息。很抱歉,我在metro,所以我需要时间写一个更详细的解释。请看我修改过的答案谢谢你的解释。我做了阅读和测试。INI设置“serialize_precision”是导致该行为的原因。所以现在我知道了为什么会这样,我可以修复这个系统,让它工作。(不,我不打算更改设置,但这对于理解问题非常重要)是的,据我所知,这是许多服务器中使用的默认精度,但如果您愿意,可以覆盖它。很高兴知道你已经进入了下一个阶段。快乐的编码兄弟!您正在使用哪个PHP版本。还是PHP5.x?是的,谢谢。我不知道这个设置。现在,我做了更多的阅读和游戏设置要做的事情:概念验证“,这一切都是有意义的
ini_set('serialize_precision',"-1");