简体   繁体   English

浮点循环运行的迭代次数应该比应有的多

[英]Floating point loop runs more iterations than should be

I have this loop thats supposed to iterate lx times over x (range [-1,1]) and ly times over y (range [-1,1]), 9 times total, yet it iterates 16 times! 我有这样的循环这就是应该迭代lx超过X(范围[-1,1])和倍ly超过y倍的(范围[-1,1]),总9倍,但它迭代16倍! Why is this?? 为什么是这样??

#include <stdio.h>

int main(void) {
  double lx=3,ly=3;
  double du = (1-(-1))/double(lx);
  double dv = (1-(-1))/double(ly);
  int count=0;

  for (double y=-1; y < 1; y += dv)
    for (double x=-1; x < 1; x += du) {

      count++;
    }

  printf("\n\n%d lss\n", count);
}

Seriously? 真的吗?

You are iterating over [-1, -1/3, 1/3, 1]. 你正在迭代[-1,-1 / 3,1 / 3,1]。

You can see this by putting an output statement in the loop to see what's happening. 你可以通过在循环中放置一个输出语句来查看发生了什么。

I assume your C implementation use IEEE-754 64-bit binary floating-point for double , which is the most common choice. 我假设你的C实现使用IEEE-754 64位二进制浮点数为double ,这是最常见的选择。

Every numerical arithmetic system is inexact, so the numbers you work with are not the same numbers you would get with exact mathematics. 每个数值运算系统都是不精确的,所以你使用的数字与精确数学所得的数字不同。

The statement double du = (1-(-1))/double(lx); 声明double du = (1-(-1))/double(lx); sets du to the double value that is closest to 2/3, which is 0.66666666666666662965923251249478198587894439697265625. du设置为最接近2/3的double值,即0.66666666666666662965923251249478198587894439697265625。

In the first iteration of the outer loop, y is -1. 在外循环的第一次迭代中, y为-1。 When du is added to it at the end of each iteration, the results are: 在每次迭代结束时将du添加到其中时,结果为:

  • -0.33333333333333337034076748750521801412105560302734375, -0.33333333333333337034076748750521801412105560302734375,
  • 0.3333333333333332593184650249895639717578887939453125, and 0.3333333333333332593184650249895639717578887939453125,和
  • 0.99999999999999988897769753748434595763683319091796875. 0.99999999999999988897769753748434595763683319091796875。

Obviously, that last value of y is less than 1, so the loop continues for another iteration. 显然, y最后一个值小于1,因此循环继续进行另一次迭代。

Loop iterators should usually use integer values, so that it is easy to ensure exact arithmetic is used. 循环迭代器通常应该使用整数值,因此很容易确保使用精确的算术。 You can scale the iterator to produce other desired values: 您可以缩放迭代器以生成其他所需的值:

for (int iy = 0; iy < 4; ++iy)
{
    double y = iy * 2 / 3. - 1;
    …
}

You need to calculate the difference between your start and end point in a different way here as you're using doubles here. 你需要在这里以不同的方式计算起点和终点之间的差异,因为你在这里使用双打。

So instead of end - start use end - start + 1.0 and you're done. 因此,而不是end - start使用end - start + 1.0 ,你就完成了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM