How to properly iterate over a double

点点圈 提交于 2019-12-08 09:00:16

问题


I'm iterating over t like this

double dt = 0.1, t;
double tmax = 100;
for (t = 0; t <= tmax; t += dt) { /*do something*/ }

If dt is 0.1, as here, everything works as it should and the step is executed for t = 100. But if I decrease the step, for example dt = 0.001, the last step is not executed.

How should I properly iterate over doubles?


回答1:


Iterate over an integer and use a start-step formula to get each double value.

double dt = 0.1, t;
double tmax = 100;
int i, n = (int)(tmax / dt); // n: check your rounding or specify explicitly.
for (i = 0; i <= n; i++) { t = 0/*start*/ + dt * i; /*do something*/ }



回答2:


Your code is fine, and the behavior is expected. Ok, not expected, but explainable due to how floating point numbers work. Look here http://floating-point-gui.de/ In case the link disappears one day, google "what programmers should know about floating point" - I'm sure it'll be cached somewhere!




回答3:


Instead of

for (t = 0; t <= tmax; t += dt) { /*do something*/ }

write:

double i;
for (i = 0; i <= 1000; i += 1.0) { 
  t = i / 10.0;
  /*do something */
}

With this pattern, the loop body will be executed exactly 1001 times and each value of t will be the nearest double approximation of the number you intended (in particular, the 11th value will be 1 exactly, the 31th value will be 3 exactly, …).

Your version does not work well because simple decimal numbers such as 0.1 or 0.01 are not representable exactly in binary floating-point.

If you are willing to adapt the number of points to the fact that you are using binary floating-point, simply use a power of two and all will be well:

for (t = 0; t <= 100.0; t += 1.0 / 64.0) { /*do something*/ }


来源:https://stackoverflow.com/questions/26821645/how-to-properly-iterate-over-a-double

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!