为什么浮点比较在不同的编译器上给出不同的输出?[复制]

Why floating point comparisons gives different outputs on different compiler? [duplicate]

提问人:Destructor 提问时间:4/30/2015 更新时间:10/16/2017 访问量:911

问:

我正在读这篇文章。它包含以下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 位: 否则 IF

5) MSVS 2010:ELSE IF,但编译时发出警告

警告 1 警告 C4305:“initializing”:从“double”截断为 “浮动”

这里到底发生了什么?程序有什么问题?是否发生了实现定义的行为?

请帮帮我。

c 精度 浮点转换

评论

0赞 4/30/2015
从技术上讲,一些编译器执行从 double 到 float 的转换,而一些编译器(输出的编译器)只是裁剪按位表示。应该是这样。输出的编译器是错误的,恕我直言ELSEELSE
0赞 phuclv 4/30/2015
重复:0.1 浮点数大于 0.1 双精度。我以为这是假的
1赞 Simon Byrne 4/30/2015
我不认为这是重复的:这个问题指的是比较 a 和 a:这是关于比较 a 和 a 字面意思。floatdoublefloat

答:

2赞 Sadique 4/30/2015 #1

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

[标志][尾数] * 2[指数]

因此,当内存中的空间较少时,会出现舍入或相对错误。

来自维基

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

enter image description here

IEEE 754 标准将二进制文件32 指定为:

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

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

更大(更多位)的浮点表示形式可实现更高的精度

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

每个计算机科学家都应该了解的浮点运算知识

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

评论

0赞 Antti Haapala -- Слава Україні 12/27/2017
嗨,您是否考虑将其标记为移动到重复目标中;这将是对副本中答案的非常好的补充