比较浮点数和双精度浮点数

3
#include <stdio.h>
int main(void){
    float a = 1.1;
    double b = 1.1;
    if(a == b){
        printf("if block");
    }
    else{
        printf("else block");
    }
    return 0;
}

打印:else块

#include <stdio.h>
int main(void){
    float a = 1.5;
    double b = 1.5;
    if(a == b){
        printf("if block");
    }
    else{
        printf("else block");
    }
    return 0;
}

输出:if 块

这背后的逻辑是什么?

编译器使用:gcc-4.3.4


尝试在编译器中打开“-Wfloat-equal”。这是一个有用的警告。 - Borealid
3个回答

6

这是因为在二进制浮点数中无法完全表示1.1,但可以表示1.5

因此,floatdouble的表示将会有稍微不同的1.1值。

下面是用二进制浮点数写出的这种差异:

(float) 1.1 = (0.00011001100110011001101)₂
(double)1.1 = (0.0001100110011001100110011001100110011001100110011010)₂

因此,当你比较它们时(且 float 版本被提升),它们将不相等。

第一个零应该是一;这只是在浮点表示中隐含的 :D - Antti Haapala -- Слава Україні


1
1.1的确切二进制值是无限小数1.00011001100110011001100(1100).... 双精度常量1.1是该尾数53位截断/近似值。现在,将其转换为浮点数时,尾数将仅用24位表示。

当将float转换回double时,尾数现在恢复到53位,但超过24位的所有数字都丢失了——该值被零扩展,现在您正在比较(例如,取决于舍入行为)。

1.0001100110011001100110011001100110011001100110011001

并且

1.0001100110011001100110000000000000000000000000000000

现在,如果你使用1.5而不是1.1;
1.5十进制恰好等于二进制中的1.1。它可以用只有2位的尾数精确表示,所以即使使用24位浮点数也是夸张的...你所拥有的是
1.1000000000000000000000000000000000000000000000000000

并且

1.10000000000000000000000

后者,零扩展为双精度浮点数将是:
1.1000000000000000000000000000000000000000000000000000

显然是同一个数字。


谢谢提供额外信息 :) - Chankey Pathak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接