For-loop in C++ using double breaking out one step early, boundary value not reached

后端 未结 10 633
难免孤独
难免孤独 2020-12-06 03:24

I have a simple C++ program compiled using gcc 4.2.4 on 32-bit Ubuntu 8.04. It has a for-loop in which a double variable is incremented from zero t

相关标签:
10条回答
  • 2020-12-06 03:50

    You should not use == or <= for doubles due to its internal representation. On last step you'll get 0.95000000000000029. Instead you could use the following code:

    stepSize = 0.05;
    // stepSize/2 looks like a good delta for most cases
    for (double index = rangeMin; index < rangeMax+stepSize/2; index+= stepSize)
    {
        cout << index << endl;
    }
    

    For more details read What Every Computer Scientist Should Know About Floating-Point Arithmetic.

    0 讨论(0)
  • 2020-12-06 03:51

    Most exact decimals do not have an exact finite representation in floating point arithmetic.

    You need to read Goldberg's What Every Computer Scientist Should Know About Floating-Point Arithmetic.

    0 讨论(0)
  • 2020-12-06 03:51

    This is due to the inexact representation of decimal fractions by floating-point numbers. Your step size isn't actually 0.1 or 0.05, it's some other value that's very close. The slight error accumulates as you go through the loop.

    To solve this problem, you have to avoid comparing floating-point numbers for equality.

    0 讨论(0)
  • 2020-12-06 03:57

    As others have said, not every real number is exactly representable as a floating point value, so you can expect a small, "random" rounding error in floating-point calculations. It is similar to what happens with normal decimal digits: 1/3 isn't exactly representable using three decimal digits (0.33), so (1/3)*3 would become 0.99 and not exactly 1.

    It is possible to use some sort of "precision" in your comparisons, but I would recommend avoiding floating-point numbers for loops, and instead use integers.

    For example, your loop

    stepSize = 0.05;
    for (double index = rangeMin; index <= rangeMax; index+= stepSize)
    {
        cout << index << endl;
    }
    

    could be replaced by something along the lines of

    stepSize = 0.05;
    for (int index = 0; index < 21; ++index)
    {
        double value = rangeMin + index * stepSize;
        cout << value << endl;
    }
    
    0 讨论(0)
  • 2020-12-06 04:01

    As mentioned by others, this is a well known issue due to the inexact representation of certain decimal numbers in memory. I would highly recommend reading What Every Computer Scientist Should Know About Floating-Point Arithmetic and IEEE floating-point representations of real numbers.

    0 讨论(0)
  • 2020-12-06 04:04

    Generally, when you compare doubles, simple comparison is not good enough, and you should compare them "up to a precision". i.e. :

    if ( fabs(double1-double2) < 0.0000001 ) {
      do-something
    }
    

    The problem occurs due to the representation of double variables.

    0 讨论(0)
提交回复
热议问题