-1

编辑:这里有很多不满的成员,因为这个问题在网站上有重复。在我的辩护中,我尝试先搜索答案,也许我使用了糟糕的搜索关键字,但我找不到这个特定代码示例的直接、明确的答案。我几乎不知道有一个从** 2009 **开始,然后会从这里链接到。

这是一个编码示例:

#include <iostream>
using namespace std;

int main() {
    float x = 0.1 * 7;
    if (x == 0.7)
        cout << "TRUE. \n";
    else
        cout << "FALSE. \n";

    return 0;
}

这导致 FALSE。但是,当我输出 x 时,它确实输出为 0.7。解释?

4

4 回答 4

7

请阅读每个计算机科学家应该了解的关于浮点运算的知识

首先,0.1是类型的文字double。IEEE 754 双精度中最接近 0.1 的可表示值是:

0.1000000000000000055511151231257827021181583404541015625

如果将其乘以 7,IEE 754 单精度中最接近的可表示值(因为您将其存储在 a 中float)是:

0.699999988079071044921875

如您所见,这几乎是0.7,但不完全是。然后将其转换为 adouble进行比较,您最终会比较以下两个值:

0.699999988079071044921875 == 0.6999999999999999555910790149937383830547332763671875

哪个当然评估为false.

于 2013-04-28T21:33:21.520 回答
1

这是因为数字以二进制形式存储。在二进制中,您不能用有限多个位置精确地表示分数 .1 或 .7,因为它们在二进制中具有重复扩展。像 1/2 这样的东西可以用 .1 来精确表示,但是十进制的 0.1 是 .0001100110011.... 所以,当你截掉这个数字时,你肯定会出现舍入误差。

于 2013-04-28T21:34:01.733 回答
0

操作员永远不应该比较双精度和浮点数==。数字不准确地存储在内存中,因为在二进制中它们不必具有有限表示(例如 0.1)。

你会在这里看到它:

#include <iostream>
using namespace std;

int main() {
    float x = 0.1 * 7;
    cout << x-0.7;
    return 0;
}

差异不是零,而是非常接近于零的东西。

于 2013-04-28T21:34:00.963 回答
0

像每个数据类型一样,浮点数表示为二进制数。有关确切的表示,请参见此处:http ://en.wikipedia.org/wiki/IEEE_floating_point

手动将十进制数转换为浮点数时,首先必须将其转换为定点数。

将 0.7 转换为基数 2(二进制):

0.7 = 0.101100110011...

如您所见,它在逗号后有无限位,因此当将其表示为浮点数据类型时,一些数字将被截断。这导致在将其转换回十进制时,数字不完全是 0.7。

在您的示例中,乘法的结果与文字“0.7”不同。

要解决此问题:在比较浮点数的相等性时使用 epsilon:

if (x < 0.71f && x > 0.69f)
于 2013-04-28T21:36:26.797 回答