为了账号安全,请及时绑定邮箱和手机立即绑定

PHP var_dump 不一致,浮点计算的楼层结果错误

PHP var_dump 不一致,浮点计算的楼层结果错误

PHP
大话西游666 2023-09-08 14:33:00
对于这段代码:$value = 200.1;$denominator = 0.1;echo "value: $value\n";echo "denominator: $denominator\n";$resultInt = ($value / $denominator);echo "($value / $denominator) = ";printf ("%f\n", $resultInt);$resultInt = (int) ($value / $denominator);echo "(int) ($value / $denominator) = ";printf ("%f\n", $resultInt);$resultInt = floor($value / $denominator);echo "floor($value / $denominator) = ";printf ("%f\n", $resultInt);$resultInt = floor((int) ($value / $denominator));echo "floor((int) ($value / $denominator)) = ";printf ("%f\n", $resultInt);$resultInt = floor((float) 2001);echo "floor((float) 2001) = ";printf ("%f\n", $resultInt);$resultInt = round($value / $denominator, PHP_ROUND_HALF_DOWN);echo "round($value / $denominator, PHP_ROUND_HALF_DOWN) = ";printf ("%f\n", $resultInt);$valueMul = $resultInt * $denominator;if ($valueMul !== $value) {    echo "they are not the same\n";    var_dump($value);    var_dump($valueMul);}$valueDiff = $value - $valueMul;if ($valueDiff !== 0) {    echo "valueDiff is not zero\n";    var_dump($valueDiff);}我有这个结果:value: 200.1denominator: 0.1(200.1 / 0.1) = 2001.000000(int) (200.1 / 0.1) = 2000.000000floor(200.1 / 0.1) = 2000.000000floor((int) (200.1 / 0.1)) = 2000.000000floor((float) 2001) = 2001.000000round(200.1 / 0.1, PHP_ROUND_HALF_DOWN) = 2001.000000they are not the samefloat(200.1)float(200.1)valueDiff is not zerofloat(-2.8421709430404E-14)上述所有计算的预期结果是 2001,但在某些情况下它是 2000。我知道由于计算机在二进制上运行,因此分数不会以小数形式存储在变量中。但正如地板手册所述:地板 -向下舍入分数因此我期望得到与以下相同的结果:round(200.1 / 0.1, PHP_ROUND_HALF_DOWN)但 round 按预期返回 2001,而下限返回 2000(错误)。你知道为什么吗?我还发现这var_debug是不一致的:
查看完整描述

1 回答

?
慕斯王

TA贡献1864条经验 获得超2个赞

您遇到了精度问题。在 PHP 中,您永远不应该相信浮点数的最后一位数字。

从手册(浮点数)中,第二段甚至有关于您的特定测试数字的一点:

浮点数的精度有限。虽然这取决于系统,但 PHP 通常使用 IEEE 754 双精度格式,由于按 1.11e-16 的顺序舍入,这将给出最大相对误差。非初等算术运算可能会产生较大的误差,当然,当多个运算复合时,必须考虑误差传播。

此外,可以精确表示为以 10 为基数的浮点数的有理数(例如 0.1 或 0.7),没有精确表示为以 2 为基数的浮点数(无论尾数的大小如何,在内部使用)。因此,它们无法在不损失少量精度的情况下转换为内部二进制对应项。这可能会导致令人困惑的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期的 8,因为内部表示类似于 7.9999999999999991118...

因此,永远不要相信浮点数结果到最后一位,也不要直接比较浮点数是否相等。如果需要更高的精度,可以使用任意精度数学函数和 gmp 函数。

查看完整回答
反对 回复 2023-09-08
  • 1 回答
  • 0 关注
  • 73 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信