【问题标题】:Why floating point comparisons gives different outputs on different compiler? [duplicate]为什么浮点比较在不同的编译器上给出不同的输出? [复制]
【发布时间】:2015-04-30 08:33:39
【问题描述】:

我正在阅读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(见运行:http://ideone.com/VOE3E0)

4) TDM GCC 32 位:ELSE IF

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

警告 1 警告 C4305:“正在初始化”:从“双”截断到 '浮动'

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

请帮帮我。

【问题讨论】:

  • 从技术上讲,一些编译器执行从 double 到 float 的转换,而一些(输出 ELSE 的编译器)只是裁剪按位表示。应该是这样。输出ELSE 的编译器是错误的,恕我直言
  • 我不认为这是重复的:这个问题是指比较 float 和 double:这是关于比较 float 和文字。

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


【解决方案1】:

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

[符号] [尾数] * 2[指数]

所以当内存空间较小时会出现舍入或相对误差。

来自wiki:

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

IEEE 754 标准将 binary32 指定为:

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 这样的简单值不能用二进制浮点数精确表示,而浮点数的精度有限意味着运算顺序的微小变化可能会改变结果。必读:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

【讨论】:

  • 嗨,您是否考虑将其标记为移动到重复目标;这将是对副本中答案的很好补充
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
相关资源
最近更新 更多