浮点比较`a!= 0.7`

Ash*_*ave 4 c floating-point comparison

可能重复:
浮点比较中的问题

#include <stdio.h>
#include <conio.h>

main()
{
    float a = 0.7;
    if(a < 0.7)
        printf("C");
    else
        printf("C++");
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,输出是C.我在Code :: Blocks和Pelles C中尝试了这个代码,但得到了相同的答案.我想详细了解这个的原因!

Ste*_*non 20

在二进制中,0.7是:

b0.1011001100110011001100110011001100110011001100110011001100110...
Run Code Online (Sandbox Code Playgroud)

但是,0.7是一个双精度文字,其值为0.7舍入到最接近的可表示的双精度值,即:

b0.10110011001100110011001100110011001100110011001100110
Run Code Online (Sandbox Code Playgroud)

十进制,这正是:

 0.6999999999999999555910790149937383830547332763671875
Run Code Online (Sandbox Code Playgroud)

写入时float a = 0.7,该double值再次舍入为单精度,并a获取二进制值:

b0.101100110011001100110011
Run Code Online (Sandbox Code Playgroud)

这正是

 0.699999988079071044921875
Run Code Online (Sandbox Code Playgroud)

十进制.

进行比较时(a < 0.7),您将此单精度值(转换为double,因为所有单精度值都可以双精度表示)与原始双精度值进行比较.因为

 0.699999988079071044921875 < 0.6999999999999999555910790149937383830547332763671875
Run Code Online (Sandbox Code Playgroud)

比较正确返回true,并打印您的程序"C".

请注意,这在C++中没有任何不同,相反的代码的出现.某些(数字上不安全的)编译器优化可以改变行为,但这些优化并不是C或C++独有的.


unk*_*ulu 8

这是因为0.7有类型double,所以a转换为double和这种类型进行比较.由于0.7在二进制浮点中无法准确表示,因此会出现一些舍入误差,并且比较变为真.

您可以:

if( a < 0.7f ) {
....
Run Code Online (Sandbox Code Playgroud)

但实际上这种效果对C++也是如此,所以你的条件并不完全正确.