C++ 中的 For 循环使用双突破提前一步,未达到边界值

2021-12-11 00:00:00 for-loop floating-accuracy c++

我有一个在 32 位 Ubuntu 8.04 上使用 gcc 4.2.4 编译的简单 C++ 程序.它有一个 for 循环,其中 double 变量以特定步长从 0 递增到 1.当步长为 0.1 时,行为正是我所期望的.但是当步长为'0.05'时,循环在0.95后退出.谁能告诉我为什么会这样?输出遵循下面的源代码.

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 to one with a certain step size. When the step size is 0.1, the behavior is what I expected. But when the step size is '0.05', the loop exits after 0.95. Can anyone tell me why this is happening? The output follows the source code below.

#include <iostream>

using namespace std;

int main()
{
    double rangeMin = 0.0;
    double rangeMax = 1.0;
    double stepSize = 0.1;

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

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

    return 0;
}

输出

sarva@savija-dev:~/code/scratch$ ./a.out 
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1

0
0.05
0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
0.55
0.6
0.65
0.7
0.75
0.8
0.85
0.9
0.95
sarva@savija-dev:~/code/scratch$

推荐答案

当使用浮点值时,并非每个值都可以精确表示,0.95+0.05 >1 因为 0.95 不能完全用 double 值表示.

When using floating point values not every value is exactly representable, 0.95+0.05 > 1 because 0.95 is not exactly representable by a double value.

看看维基百科对浮点精度的看法.

See what Wikipedia has to say about floating point accuracy.

如果您查看 IEEE 浮点转换器,您会看到0.95 在 64 位浮点数 (double) 中的值是 0-01111111110-1110011001100110011001100110011001100110011000 输入这个http://www.ajdesigner.com/fl_ieee_754_word/ieee_32_bit_word.php" rel="nofollow noreferrer">浮点计算器 你得到的值为 0.95000016 并添加 0.05 将带您超越 1.0 标记.

If you look at the IEEE floating point converter you'll see that the value of 0.95 in 64 bit floating point (double) is 0-01111111110-1110011001100110011001100110011001100110011001100110 by entering this in a floating point calculator you get the value is 0.95000016 and adding 0.05 to that takes you over the 1.0 mark.

这就是为什么你永远不应该在循环中使用浮点数(或者更一般地说,将浮点计算的结果与精确值进行比较).

This is why you should never use floating points in loops (or more generally compare the result of floating point calculation to an exact value).

相关文章