I would like to iterate over a range of floating point numbers, such as in the following example.

for (double d = 1.0; d <= 2.0; d += 0.1)
{
   cout << d << endl;
}

Because it is impossible to represent 0.1 accurately, the last value of 2.0 is not printed.

How can I ensure that the last value in this case and similar cases is not omitted?

有帮助吗?

解决方案

Loop over integers, and divide by a floating point number:

#include <iostream>
#include <iomanip>

int main()
{
  std::cout << std::setprecision(1) << std::fixed;

  for (int d = 10; d <= 20; ++d)
  {
     std::cout << d/10. << std::endl;
  }
}

Output:

1.0
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2.0

其他提示

Due to floating point numbers not being accurate in such kind of situations I usually work around by "emulating" them through integers. At least for simple cases like this one.

for (int i = 10; i <= 20; ++i)
{
   cout << i / 10.0 << endl;
}

That should give you the closest you can get with floating points for any of the values.

If you're using fixed increments (like in your example), one way is to use integers:

for (int i = 10; i != 20; ++i)
{
   cout << (i / 10.0) << endl;
}

It would be best to use and update an integer value to control your loop. And a use and update a floating point value to use to output. I'm assuming your real-world case is a little more complex than this.

This will execute the loop the correct number of times and save on int to float conversions. The double value will be accurate so long as you don't loop too many times or let it get too big, then you will start getting rounding errors. In general you can come up with ways to correct for this, but with a loop of size/range it's a non-issue.

double d = 1.0;
for (unsigned i = 0; i <= 10; ++i, d += 0.1)
{
   cout << d << endl;
}

If you want to avoid cumulative round-off error from adding 0.1, it can be done like this:

double d = 10.0;
for (unsigned i = 0; i <= 10; ++i, d += 1.0)
{
   cout << (d / 10.0) << endl;
}

This is more accurate because small whole numbers can be represented accurately in a floating point format. However it costs a floating point division, but still avoids the int-to-float conversions.

for (double d = 1.0; d <= 2.02; d += 0.1)
{
   cout << d << endl;
}

Comparing double to be equal is hard work, but slight increase it will do the trick.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top