3

当我运行时:

for($o=1;$o<=655;$o++){ $r = $r+0.01; echo $r." ";}

在某些时候我得到:

...4.29 4.3 4.31 4.32 4.33 4.34 4.35 4.36 4.37 4.38 4.39 4.4
4.41 4.42 4.4299999999999 4.4399999999999 4.4499999999999
4.4599999999999 4.4699999999999 ...

但是当我运行时:

for($o=1;$o<=5;$o+=0.01){ echo $o." "; }

异常开始于:

4.34 4.35 4.36 4.37 4.38 4.3899999999999 4.3999999999999

为什么加法是 for 循环的一部分,还是在 for 循环中?

4

4 回答 4

5

欢迎来到舍入误差的奇迹。

0.01 不能完全表示为有限二进制分数,因此如果将其重复添加到另一个浮点数,最终会出现舍入误差。

您看到舍入误差的具体点取决于所涉及数字的二进制扩展如何产生舍入误差。

于 2012-11-07T23:17:11.410 回答
1

浮点数学不能准确地表示这些值。见这里

于 2012-11-07T23:17:23.533 回答
1

当数字“.01”转换为 64 位 IEEE 754 二进制浮点时,结果为 0.010000000000000000208166817117216851329430937767028809。当 $r 设置为 0 并将这个 0.01 的近似值添加到它 100 次时,结果是 1.0000000000000006661338147750939242541790008544921875,因为在添加过程中存在额外的舍入误差。

现在考虑 $r 从这个值进一步增加 1,而 $o 从它的起始值正好 1 增加。首先,由于 $r 和 $o 以不同的值开始,所以它们以后通常会有不同的值。其次,因为它们不同,当增量被添加到它们中时,它们在加法中遇到来自四舍五入的不同错误。这个错误可能会加强或取消,导致 $r 或 $o 或多或少不同。

最后,PHP 有一些标准来决定是否打印带有两个或更多小数点的数字。据推测,在某些时候,$r 或 $o 的值距离最近的带有两个小数点的数字足够远,PHP 决定它应该打印更多的数字。如上所述,对于 $r 和 $o,这发生在不同的时间。

于 2012-11-08T01:26:47.467 回答
0

您可以使用 Round() 函数。这是一个链接: http: //php.net/manual/en/function.round.php

于 2012-11-07T23:50:01.723 回答