如何使用 fmod 并避免精度问题

How to use fmod and avoid precision issues

我要把这个问题归结为最简单的形式:

Let's iterate from [0 .. 5.0] with a step of 0.05 and print out 'X' for every 0.25 multiplier.

for(double d=0.0; d<=5.0; d+=0.05) {
  if(fmod(d,0.25) is equal 0)
    print 'X';
}

这当然不起作用,因为 d 将是 [0, 0.05000000001, 0.100000000002, ...] 导致 fmod() 失败。极端的例子是 d=1.999999999998fmod(d,0.25) = 1.

如何解决这个问题? Here is 一个可编辑的在线示例。

我会通过不以这种方式使用浮点变量来解决这个问题:

for (int i = 0; i <= 500; i += 5) {
  double d = i / 100.0;  // in case you need to use it.
  if ((i % 25) == 0)
    print 'X';
}

它们通常问题重重,值得多加努力避免它们。

如果您始终使用相同的固定小数部分,只需将循环计数器乘以(在本例中乘以 20)即可。当你想将它作为双精度数访问时,除以 20。实际上,你正在使用一个隐藏的指数来让你的双精度数保持整数。

在示例中,我使用整数作为循环计数器,假设它具有所需的精度。

for(int i=0; i<=100; i+=1) {
  if(i % 5 == 0)
    print 'X';
  double d = (double)i / 20.0;
  // use d
}