C:使用float和double时出现奇怪的错误

C:使用float和double时出现奇怪的错误,c,floating-point,C,Floating Point,可能重复: 我有一个C语言的double和float测试,但我无法解释为什么 float x = 3.4F; if(x==3.4) printf("true\n"); else printf("false\n"); double y = 3.4; if (y==3.4) printf("true\n"); else printf("false\n"); 结果将是错误的和真实的。请给我解释一下。x==3.4应该是

可能重复:

我有一个C语言的double和float测试,但我无法解释为什么

    float x = 3.4F;
    if(x==3.4)
        printf("true\n");
    else printf("false\n");
    double y = 3.4;
    if (y==3.4)
        printf("true\n");
    else printf("false\n");

结果将是错误的和真实的。请给我解释一下。

x==3.4
应该是
x==3.4F
,否则3.4是双精度的(默认情况下)。要经常比较同类,而不是苹果和桔子

编辑: 不同精度类型之间的比较结果是真是假取决于编译器的浮点表示形式


浮点数,无论是单精度(float)还是双精度,都是近似值。

不保证结果是假的和真的,但基本思想非常简单:
3.4
有double类型。当您将其分配给一个
浮点值时,它将四舍五入。比较时,舍入的数字将被提升回双精度,而不一定是与
3.4
相同的双精度

在第二种情况下,整个过程都是双倍的。

比较是否相等 浮点数学是不精确的。像0.2这样的简单值不能用二进制浮点数精确表示,而浮点数的有限精度意味着操作顺序的细微变化可能会改变结果。不同的编译器和CPU体系结构以不同的精度存储临时结果,因此根据环境的细节,结果会有所不同。如果您进行计算,然后将结果与某个预期值进行比较,则极不可能得到准确的预期结果

换句话说,如果进行计算,然后进行比较: 如果(结果==expectedResult)


那么,这种比较不太可能是真的。如果比较是真的,那么它可能是不稳定的——输入值、编译器、,或者CPU可能会更改结果并使比较结果为假。

3.4不能精确表示为双精度,原因与三分之一不能使用有限位数精确表示为以10为基数的十进制数相同——表示是递归的

因此,double literal
3.4
实际上是最接近3.4的双精度值
3.4F
是最接近3.4的浮点值,但与最接近的双精度值不同

将浮点与双精度浮点进行比较时,浮点将转换为双精度浮点,这不会更改其值


因此,
3.4F!=3.4
,正如
0.3333!=0.33333333

作为提示,在大多数情况下,比较浮点数(浮点或双精度)与“==”是一种糟糕的编程实践,因为您可能永远不会得到正确的语句。这两个数字的最低有效位可能不同

最好使用以下方法:

abs(x-y)


EQUALITY\u MARGIN
相比,这是一个足够小的数字。

是的,但有一个例外:正如我所认为的,数字与自身的比较总是正确的:
x=3.4f;if(x==3.4f)//必须为true
。所以,正如我所想,你可以比较浮点数(所以我们在C中有这样的运算符),但你必须小心。文本与自身的比较总是正确的(除了NaN,但在本例中这不相关),因为编译器将两次生成相同的实数近似值。不过,一旦你开始用这些数字做数学运算,所有的赌注都输掉了。浮点数的比较是精确的。这是一个完全指定的基本操作,当且仅当a和b表示相同的值时,“a==b”才计算为true。浮点运算出现问题不是因为比较不精确,而是因为许多运算必须对结果进行四舍五入,因为精确的结果无法表示。这种区别很重要,因为希望设计或证明浮点代码的工程师必须使用浮点运算的实际属性。许多重复项,例如和。您可能会喜欢这篇博文:@PascalCuoq Oh。非常非常好的文章:))第一次在这里,downvote+close post没有让我难过:D我对他的最后一个例子印象深刻:Dah。我看到这个博客是你的:)我看到了另一个主题,也很好;)在C语言中,默认情况下使用
double
。这是语言的一个特性,而不是特定于编译器的东西。我不是说double作为默认值是特定于编译器的,我的意思是比较效果是。很抱歉理解错误。与浮点常量进行比较的效果也在标准中定义,不应受到编译器特定功能的限制。。。您能编辑您的答案使其更清楚吗?不同精度类型之间的比较不取决于编译器的浮点表示形式。当且仅当a和b表示的值相等时,比较“a==b”计算为true。即使a和b是不同的浮点类型,这也是正确的,因为精度较低的类型将转换为精度较高的类型,而不会出现错误。说浮点数是近似值也是不正确的。精确指定浮点对象的值;每一个都表示一个单一的、精确的、完全定义的数字(或NaN)。(下面继续)引入错误的是浮点操作,而不是浮点对象或比较。当浮点运算的精确数学结果无法精确表示时,将返回舍入结果。此外,复杂的数学函数可能是近似的,例如正弦和对数,因此它们返回的结果并不总是最好的。这种关于错误发生位置的区分很重要,因为希望设计或证明浮点代码的工程师必须使用浮点运算的实际属性。