浮动比较给出了不同的结果
看看以下两个代码,并告诉我答案变化很大的原因。
#include int main() { float a = 0.9; if(a<0.9) printf("hi"); // This will be the answer else printf("bye"); return 0; }
如果我们将0.9更改为0.8,则会打印其他语句:
#include int main() { float a = 0.8; if(a<0.8) printf("hi"); else printf("bye");//this will be the answer return 0; }
那么为什么当我们改变一个数字时这个输出会改变?
您必须知道浮点的工作原理。
浮点用2的幂表示,每个数字用于表示2^-x
,其中X是第n个数字。
例如, 0.011
(二进制)将是2^-2 + 2^-3
,其为0.25 + 0.125 = 0.375
现在尝试代表0.9
。 你有麻烦,因为没有两个人的力量代表它。 在32位且可能是64位机器中表示的值将给出略小于0.9 的结果 , 而对于0.8,结果是精确的并且可由2的幂表示 。
你可以通过打开python
提示来试试这个。 尝试输入几个数字,最终会以...99999999
结束。
此错误是由浮点精度引起的,因为您将float
类型与double
值进行比较。 尝试将它与浮点文字进行比较: if(a<0.8f)
我建议你阅读维基百科的相关文章 ,它会详细解释你的错误发生的原因。
文字0.9
和0.8
类型为double
。 由于两个值都不能准确表示,它们实际上将是0.9000000000000000222...
和0.8000000000000000444...
当存储在float
(单精度)变量中时a
它们将被转换为单个并变得更加不准确: 0.89999997...
和0.8000000119...
为了与文字double
值进行比较,它们被转换回double
保留更不准确的值。
从上面的数字可以看出,这种比较产生了0.9
和0.8
不同结果。
所有这一切都假设您的平台具有IEEE754浮点数,这很可能就是这种情况。
您可以在www.binaryconvert.com上查看数字的单/双表示。
根据C标准:
6.3.1.5真正的浮动类型
1)当float被提升为double或long double,或者double被提升为long double时,其值不变。
2)当double被降级为float时,long double被降级为double或float,或者以更高的精度和范围表示的值超出其语义类型所需的值(见6.3.1.8)被显式转换为其语义类型,如果转换的值可以在新类型中准确表示,则它保持不变。 如果被转换的值在可以表示但不能精确表示的值的范围内,则结果是以实现定义的方式选择的最接近的较高或最接近的较低可表示值。 如果转换的值超出了可以表示的值范围,则行为未定义。
标准可以在这里找到。
这是由于舍入错误,要查看您使用的值在if之前插入printf:
printf("a=%f\n", a);
首先,正如其他人提到的那样,在使用float
时使用0.8f
值。
此外,浮点==
比较是您希望避免的,因为FPU中此操作的精度。 对我来说最有效的方法是定义一个保证金,比如1e-6f
(或者根据你的应用需要的精度)而不是这个:
if (LHS == RHS)
你写:
if (LHS-RHS < MARGIN && RHS-LHS < MARGIN)
你可以写一个函数(如果你是一个c ++粉丝)或宏(如果你是ac粉丝(这里是-1s))为你做这个。
试试这个:
而不是“if(a <0.9)”使用“if(a <0.9f)”进行比较