C++ 有人能向我解释为什么浮点x=0.1*7不会导致x==0.7为真吗?

C++ 有人能向我解释为什么浮点x=0.1*7不会导致x==0.7为真吗?,c++,floating-point,C++,Floating Point,编辑:这里有很多不满的成员,因为这个问题在网站上有重复。在我的辩护中,我首先尝试搜索答案,也许我使用了糟糕的搜索关键字,但我找不到这个特定代码示例的直接、清晰的答案。我一点也不知道有一个来自**2009**的链接会从这里链接到这里 下面是一个编码示例: #include <iostream> using namespace std; int main() { float x = 0.1 * 7; if (x == 0.7) cout <<

编辑:这里有很多不满的成员,因为这个问题在网站上有重复。在我的辩护中,我首先尝试搜索答案,也许我使用了糟糕的搜索关键字,但我找不到这个特定代码示例的直接、清晰的答案。我一点也不知道有一个来自**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;
}
#包括
使用名称空间std;
int main(){
浮点数x=0.1*7;
如果(x==0.7)
请仔细阅读

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

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

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

0.699999988079071044921875 == 0.6999999999999999555910790149937383830547332763671875

当然,计算结果为
false

的双精度和浮点数绝对不能由
=
运算符进行比较。数字存储在内存中不准确,因为在二进制中,它们不必具有有限的表示形式(例如0.1)

您将在此处看到:

#include <iostream>
using namespace std;

int main() {
    float x = 0.1 * 7;
    cout << x-0.7;
    return 0;
}
#包括
使用名称空间std;
int main(){
浮点数x=0.1*7;

cout这是因为数字是以二进制存储的。在二进制中,你不能用有限多的地方精确地表示分数.1或.7,因为它们在二进制中有重复的展开式。像1/2这样的东西可以用表示法精确地表示。1,但是,例如,十进制中的.1是.000110011…所以,当你去掉这个数字,您肯定会有舍入错误。

与每种数据类型一样,浮点数表示为二进制数。有关确切表示形式,请参见此处:

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

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

0.7=0.101100110011

正如您所看到的,逗号后有无限位数,因此当将其表示为浮点数据类型时,某些数字将被截断。这导致在将其转换回十进制时,数字不是精确的0.7

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

要解决此问题,请在比较浮点相等时使用ε:

if (x < 0.71f && x > 0.69f)
if(x<0.71f&&x>0.69f)

-也就是说,考虑到硬件限制,并非所有的fp都可以精确表示。这个答案应该有助于@Mystical,我希望我们可以将问题标记为该文章的副本。实际上,0.1最接近的IEEE双精度是0.10000000000000055115123125782702118158340451015625(3602879701896397*2^-55)@奇怪的是,谢谢,我想当时我使用的网站也给了我一个错误的0.7作为双精度的值。一个超小调的评论:这个程序在数学上并没有用
7
乘以
0.10000000000000555115123125782702118158340451015625
,然后把它四舍五入
float
,就像你所暗示的那样通过
7
,将
0.10000000000000055115123125782702118158340451015625
四舍五入到
double
(这两个运算在
double
乘法中合成)然后将其四舍五入到
float
。从统计学上讲,这几乎没有什么区别,但它可以产生差异。@PascalCuoq非常正确。谢谢。@PascalCuoq:它可能会这样做,或者它可能会将它们相乘,四舍五入到长双精度,然后四舍五入到float,或者它可能会完全做其他事情。你当然知道这一点。
if (x < 0.71f && x > 0.69f)