PHP 中的浮点数 -- 奇怪的行为
Floating point numbers in PHP -- strange behaviour
有人可以解释这里发生了什么吗?我有一个浮点数,要四舍五入到小数点后两位(价格)。
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
因此,“echo”舍入到自身。当我使用 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,它将输出(或 return)变量的可解析字符串表示形式,在这种情况下,它还将 return 所有当您的数据存储为浮点变量时的数据。
这就是为什么当你执行以下命令时
var_export(round((float)$total,2));
系统会先将$total四舍五入到79.95,但是因为你指定了float cast,它会按照系统的数据精度存储它,所以当你使用var_export忠实地return 数据,它会给你类似的东西
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 中的设置。
有人可以解释这里发生了什么吗?我有一个浮点数,要四舍五入到小数点后两位(价格)。
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
因此,“echo”舍入到自身。当我使用 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,它将输出(或 return)变量的可解析字符串表示形式,在这种情况下,它还将 return 所有当您的数据存储为浮点变量时的数据。
这就是为什么当你执行以下命令时
var_export(round((float)$total,2));
系统会先将$total四舍五入到79.95,但是因为你指定了float cast,它会按照系统的数据精度存储它,所以当你使用var_export忠实地return 数据,它会给你类似的东西
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 中的设置。