浮点比较`a!= 0.7`
可能重复:
浮点比较中的问题
#include #include main() { float a = 0.7; if(a < 0.7) printf("C"); else printf("C++"); }
在上面的代码中,输出是C
我在Code :: Blocks和Pelles C中尝试了这段代码,但得到了相同的答案。 我想详细了解这个的原因!
在二进制中,0.7是:
b0.1011001100110011001100110011001100110011001100110011001100110...
但是, 0.7
是双精度文字,其值为0.7舍入到最接近的可表示的双精度值,即:
b0.10110011001100110011001100110011001100110011001100110
十进制,这正是:
0.6999999999999999555910790149937383830547332763671875
当你写float a = 0.7
,该double值再次舍入为单精度, a
得到二进制值:
b0.101100110011001100110011
这正是
0.699999988079071044921875
十进制。
当您进行比较(a < 0.7)
,您将此单精度值(转换为double,因为所有单精度值都可以双精度表示)与原始双精度值进行比较。 因为
0.699999988079071044921875 < 0.6999999999999999555910790149937383830547332763671875
比较正确返回true,程序打印"C"
。
请注意,这在C ++中没有任何不同,相反的代码的出现。 某些(数字上不安全的)编译器优化可以改变行为,但这些优化并不是C或C ++独有的。
这是因为0.7
具有double
类型,因此a
被转换为double
并且在此类型中进行比较。 由于0.7
在二进制浮点中无法准确表示,因此会出现一些舍入误差,并且比较成立。
您可以:
if( a < 0.7f ) { ....
但实际上这种效果对C ++也是如此,所以你的条件并不完全正确。
巴特在评论中给出了很好的参考,但我也建议这个非常简单的规则:
并非所有数字都可以在计算机中准确表示,因此只要使用浮点数(例如float和double),就应该期望每个存储的数字中都存在一个小的,不可预测的错误。 不,它不是真正的随机或不可预测,但在你了解更多信息之前,你可以认为它是不可预测的。 因此,诸如a <0.7之类的比较结果可能是真实的,也可能不是。 不要编写依赖于它的代码。