为什么浮点比较会在不同的编译器上提供不同的输出?

时间:2015-04-30 08:33:40

标签: c floating-point floating-accuracy floating-point-conversion

我正在阅读this。它包含以下C程序。

#include<stdio.h>
int main()
{
    float x = 0.1;
    if (x == 0.1)
        printf("IF");
    else if (x == 0.1f)
        printf("ELSE IF");
    else
        printf("ELSE");
}

文章说

  

上述程序的输出是“ELSE IF”,表示“x   == 0.1“返回false,表达式”x == 0.1f“返回true。

但我在不同的编译器上尝试过它。得到不同的产出:

以下是各种IDE的输出。

1)Orwell Dev C ++:ELSE

2)代码块13.12:ELSE IF但在编译期间它会发出以下警告。

  

警告:将浮点数与==或!=进行比较是不安全的。

为什么这种比较不安全?

3)Ideone.com:ELSE IF(见run:http://ideone.com/VOE3E0

4)TDM GCC 32位:ELSE IF

5)MSVS 2010:ELSE IF但是会发出警告

  

警告1警告C4305:'初始化':从'double'截断到   '浮动'

这里到底发生了什么?该计划有什么问题?它是否实现了定义的行为?

请帮帮我。

1 个答案:

答案 0 :(得分:2)

浮点数可以用以下形式表示:

  

[sign] [尾数] * 2 [指数]

当内存空间较小时,会出现舍入或相对错误。

来自wiki

  

单精度浮点格式是计算机数字格式,在计算机内存中占用 4字节(32位),并使用浮点表示宽动态范围的值。

enter image description here

IEEE 754标准将binary32指定为:

Sign bit: 1 bit
Exponent width: 8 bits
Significand precision: 24 bits (23 explicitly stored)
  

这从 6到9有效十进制数字精度(如果a   最多6个有效小数的十进制字符串转换为IEEE   754单精度然后转换回相同的数量   有效小数,则最终字符串应与原始字符串匹配;   如果IEEE 754单精度转换为十进制字符串   至少有9个有效小数,然后转换回单个,   那么最终的数字必须与原来的[4]相匹配。

更大(更多位)的浮点表示允许更高的精度

浮点数学并不准确。像0.1这样的简单值无法使用二进制浮点数精确表示,浮点数的有限精度意味着操作顺序的微小变化可能会改变结果。必须阅读:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

  

IEEE标准将异常分为5类:溢出,下溢,除零,无效操作和不精确。每个异常类都有一个单独的状态标志。前三个例外的含义是不言而喻的。无效操作涵盖表D-3中列出的情况,以及涉及NaN的任何比较。