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
为什么?
答案 0 :(得分:130)
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相同,为double。在这种情况下,0.7当浮动变得低于0.7时,它被提升为双倍。正如Christian所说,0.5是2的幂总是完全表示,所以测试按预期工作:0.5 < 0.5
是假的。
所以:
float
更改为double
或:.7
和.5
更改为.7f
和.5f
,你会得到预期的行为。
答案 1 :(得分:15)
问题是您要比较的常量是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
Most Effective Way for float and double comparison 上的这个问题涵盖了这个主题。
另外,这篇关于floating point number comparison的天鹅座的文章给了我们一些提示:
IEEE浮点数和双精度格式的设计是为了数字 是“按字典顺序排列的”,用IEEE的话说 建筑师威廉卡汉的意思是“如果两个浮点数 相同的格式是有序的(比如x&lt; y),然后它们的排序相同 当它们的位被重新解释为Sign-Magnitude整数时。“
这意味着如果我们在内存中使用两个浮点数,则解释它们的位 模式作为整数,并比较它们,我们可以分辨哪个更大, 没有做浮点比较。在C / C ++语言中 比较看起来像这样:
if (*(int*)&f1 < *(int*)&f2)
这种迷人的语法意味着取f1的地址,将其视为一个 整数指针,并取消引用它。所有这些指针操作看起来 昂贵,但他们基本上都取消了,只是意味着'治疗f1 作为整数'。因为我们将相同的语法应用于f2整行 表示'比较f1和f2,使用它们的内存表示 解释为整数而不是浮点数。
答案 2 :(得分:3)
这是由于从float转换为double时的舍入问题
答案 3 :(得分:2)
通常比较与浮点数的相等性是一项危险的业务(当你在&gt;的边界上进行比较时,这实际上是你所做的事情),请记住,在十进制中某些分数(如1/3)无法表达确切地说,二进制也是如此,
0.5= 0.1
,在float或double中都是相同的。
0.7=0.10110011001100
等永远,0.7不能用二进制精确表示,你得到舍入错误,并且浮点数和双精度之间可能(非常非常轻微)不同
请注意,在浮点数和双精度数之间切换不同的小数位数,因此结果不一致。
答案 4 :(得分:0)
另外,顺便说一句,你的0逻辑错误是正确的。输出0时,不检查b是否正确。但是你真正想要完成的事情有点神秘。浮点数和双精度数之间的浮点比较将具有变化,分钟,因此您应该与您的情况的delta'可接受'变化进行比较。我总是通过仅执行工作的内联函数完成此操作(使用宏执行一次,但这太麻烦了)。无论如何,是的,圆形问题比比皆是这类例子。读取浮点数,并知道.7与.7f不同,并将.7赋给float会将double转换为float,从而改变值的确切性质。但是,关于b错误的编程假设,因为你检查了一下,我不得不注意到:)