浮点比较
int main() { float a = 0.7; float b = 0.5; if (a < 0.7) { if (b < 0.5) printf("2 are right"); else printf("1 is right"); } else printf("0 are right"); }
我会期待这个代码的输出是0 are right
。 但令我沮丧的是,输出是1 is right
为什么?
int main() { float a = 0.7, b = 0.5; // These are FLOATS if(a < .7) // This is a DOUBLE { if(b < .5) // This is a DOUBLE printf("2 are right"); else printf("1 is right"); } else printf("0 are right"); }
浮点数在比较中被提升到了两倍,而且由于浮点数比双精度要低,所以0.7的浮点数不等于0.7的两倍。 在这种情况下,作为浮点数的0.7比升到0.7时小0.7。 正如克里斯蒂安所说的那样,0.5是2的幂总是精确地表示,所以testing按预期工作: 0.5 < 0.5
是错误的。
所以:
- 将
float
更改为double
,或者: - 将
.7
和.5
改为.7f
和.5f
,
你会得到预期的行为。
问题是你比较的常量是double
而不是float
。 另外,把你的常量改成可以容易表示的东西,例如5
的因子,就会说0 is right
。 例如,
main() { float a=0.25,b=0.5; if(a<.25) { if(b<.5) printf("2 are right"); else printf("1 is right"); } else printf("0 are right"); }
输出:
0 are right
这个问题最有效的方法进行浮动和双重比较涵盖了这个话题。
另外,这篇关于浮点数比较的 cygnus文章给了我们一些提示:
IEEE浮点数和双精度格式的devise使数字是“字典顺序排列”,用IEEE架构师威廉·卡汉(William Kahan)的话来说,意思是“如果相同格式的两个浮点数是有序的(比如x <y),那么当它们的位被重新解释为符号量级整数时,它们以相同的方式sorting。
这意味着如果我们在内存中使用两个浮点数,将它们的位模式解释为整数,然后比较它们,我们可以判断哪个更大,而不进行浮点比较。 在C / C ++语言中,这个比较看起来像这样:
if (*(int*)&f1 < *(int*)&f2)
这个迷人的语法是指把f1的地址作为一个整数指针,并将其解引用。 所有这些指针操作看起来都很昂贵,但是它们基本上全部取消,只是意味着“将f1视为一个整数”。 由于我们将相同的语法应用于f2,因此整行意味着“比较f1和f2,使用它们的内存中表示将其解释为整数而不是浮点数”。
这是由于四舍五入的问题,而从浮法转换为双
通常比较平等与花车是一个危险的业务(这是有效的,你在做什么,当你比较正确的边界>),请记住,在十进制某些分数(如1/3)不能准确expression,相同可以说二元的,
0.5= 0.1
,在浮点数或者双精度数上都是一样的。
0.7=0.10110011001100
等永远,0.7不能准确地表示在二进制,你会得到舍入误差,可能(非常非常轻微)不同之间的浮动和双
请注意,浮动和双打之间切断不同的小数位数,因此您的不一致的结果。
另外,顺便说一句,你有一个错误在你的逻辑0是正确的。 输出0时不检查b是正确的。 但是整个事情对于你真正想要完成的事情有点神秘。 花车和双打之间浮点比较会有变化,所以你应该比较一下你的情况下三angular洲“可接受”的变化。 我一直都是通过内联函数来完成这个工作的(只是用macros做了一次,但是太杂乱了)。 总之,这个例子里有四舍五入的问题。 阅读浮点数的东西,并知道.7是不同的.7f和分配.7浮动将投入一个双浮动,从而改变了确切的性质的价值。 但是,关于b错误的编程假设,因为你检查了一下我,我必须注意到:)