fmod函数返回错误的结果

时间:2015-02-06 18:21:25

标签: php floating-point

我得到fmod返回错误的结果,我做错了什么?

for($i = 0.00; $i < 1; $i = $i + 0.05) {
    var_dump($i." = ".fmod($i, 0.05));
}

输出:

0.= 0
0.05 = 0
0.1 = 0
0.15 = 1.3877787807814E-17
0.2 = 0
0.25 = 0.05
0.3 = 0.05
0.35 = 0.05
0.4 = 0.05
0.45 = 0.05
0.5 = 0.05
0.55 = 0.05
0.6 = 0.05
0.65 = 0.05
0.7 = 2.7755575615629E-17
0.75 = 6.9388939039072E-17
0.8 = 1.1102230246252E-16
0.85 = 1.5265566588596E-16
0.9 = 1.942890293094E-16
0.95 = 2.3592239273285E-16

我期待每个结果都是一样的:0。

2 个答案:

答案 0 :(得分:1)

首先,fmod是准确的。因为它可以:当xy是浮点数时,fmod(x,y)的数学结果可以完全表示为浮点数。

第二,当你写0.05时,你没有得到那个数字,因为另一方面5/100不能完全表示为浮点数;当你写+时,你通常不会得到数学加法,因为这个数学加法的结果不能总是表示为浮点数(*)。

从0.0开始并重复添加0.05将很快进入不准确的+区域,因为在二进制中,0.05的最佳表示具有许多数字。随着总和变大,最后的数字必须逐渐丢弃。这就是+的不准确性来自的地方,最终导致fmod无法提供您期望的结果。

如果将0.05重复添加到零,那么0.05不完全是5/100并不重要。但由于浮点数0.05有二进制数(而不是十进制数),并且因为计算y的倍数时必须丢失其中一些数字,所以大多数倍数得到的值0.05计算fmod(y, 0.05)0.05的{​​{1}} {1}}不是零,而是表示适当整数乘以y的数学乘法与该数字的近似值{{1}}之间的差值。

(*)当数学和可以表示时,数学和就是你得到的,但有时它不能。

答案 1 :(得分:0)

这个答案涉及问题的第一次修订:

https://stackoverflow.com/revisions/28372286/1

一切正常!你可以自己计算:

fmod(0.5, 0.25);
fmod(0.5, 0.23);
fmod(0.5, 0.20);

0.25 * 2 = 0.50   | Rest 0.00
0.23 * 2 = 0.46   | Rest 0.04
0.20 * 2 = 0.40   | Rest 0.10