c - 为什么浮点比较在不同的编译器上给出不同的输出?

标签 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");
}

文章说的是

The output of above program is “ELSE IF” which means the expression “x == 0.1″ returns false and expression “x == 0.1f” returns true.

但是我在不同的编译器上尝试过并得到不同的输出:

以下是各种 IDE 上的输出。

1) Orwell Dev C++:ELSE

2) 代码块 13.12: ELSE IF 但在编译过程中给出以下警告。

warning: comparing floating point with == or != is unsafe.

为什么这种比较不安全?

3) Ideone.com:ELSE IF(请参阅运行:http://ideone.com/VOE3E0)

4) TDM GCC 32 位:ELSE IF

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

Warning 1 warning C4305: 'initializing' : truncation from 'double' to 'float'

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

请帮助我。

最佳答案

float 可以用以下形式表示:

[sign] [mantissa] * 2[exponent]

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

来自wiki :

Single-precision floating-point format is a computer number format that occupies 4 bytes (32 bits) in computer memory and represents a wide dynamic range of values by using a floating point.

enter image description here

IEEE 754 标准将二进制 32 指定为具有:

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

This gives from 6 to 9 significant decimal digits precision (if a decimal string with at most 6 significant decimal is converted to IEEE 754 single precision and then converted back to the same number of significant decimal, then the final string should match the original; and if an IEEE 754 single precision is converted to a decimal string with at least 9 significant decimal and then converted back to single, then the final number must match the original [4]).

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

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

What Every Computer Scientist Should Know About Floating-Point Arithmetic

The IEEE standard divides exceptions into 5 classes: overflow, underflow, division by zero, invalid operation and inexact. There is a separate status flag for each class of exception. The meaning of the first three exceptions is self-evident. Invalid operation covers the situations listed in TABLE D-3, and any comparison that involves a NaN.

关于c - 为什么浮点比较在不同的编译器上给出不同的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29962813/

相关文章:

c - 以深度优先顺序递归遍历一般树

c - 向链表插入新节点时程序卡住

android - 使用zlib列出android中apk文件的目录结构

assembly - 如何将浮点常量移动到 FP 寄存器中?

C++ 精度 : String to Double

javascript - 为什么 0.1+0.2+0.3 不等于 0.3+0.2+0.1?

javascript - 1.265 * 10000 = 126499.99999999999?

c++ - 错误 C2668 对来自站点 http ://h264bitstream. sourceforge.net/的重载函数代码的模糊调用

c - 这个 C 函数是不是写得很糟糕?

c++ - 浮点值在发布和调试版本中表现不同