为什么在浮点比较中,最后一个小数位数为5的浮点值能给出正确的输出,而在其他情况下却不是

Why does the float having 5 as its last decimal digit give the correct output in floating point comparisons,while in other cases it is not?

本文关键字:输出 其他 情况下 小数 最后一个 比较 为什么      更新时间:2023-10-16

我已经问过这个问题,但我不清楚这个特定子部分的答案。请参阅下面的代码:

float f=2.5;
if (f==2.5)
printf("abc");
else
printf("xyz"); //prints abc

我知道,如果我们取2.2而不是2.5,它会输出相反的结果,因为float取为double和浮点数。它们实际上不应该相等吗?我想知道为什么数字的最后一个十进制数字5会出现异常。

2.5可以写成并矢有理数,并且给定它的大小也足够小,它可以在IEEE754浮点中精确地表示2.25也可以被完美地表示。参考:https://en.wikipedia.org/wiki/Dyadic_rational


浮点数实际上不应等同于

这不过是一条经验法则。使用考虑不周的公差进行任意比较可能是有害的。浮点并没有什么神秘之处。只是它们中的大多数不能用小数表示(这是开发人员倾向于考虑的),仅此而已。

因为它可以表示为2的整数次幂。例如,2.5=5/2=5×(2-1)。这与浮点值的常用表示形式直接匹配。

如果测量一个距离,它是多少毫米?是多一点点还是少一点点?如果你放大你的标尺,它是多少微米?不是多一点还是少一点?

这说明浮点使用位来表示值的近似值,并且不能(不能总是)表示精确值。

数字2.5通过了测试,因为0.5精确地表示为二进制分数。它是2-1。事实上,2的每一个负幂都有5作为它的最后一个数字。以下是的几个例子

2^-1  = 0.5000000000000000
2^-2  = 0.2500000000000000
2^-3  = 0.1250000000000000
2^-4  = 0.0625000000000000
2^-5  = 0.0312500000000000
2^-6  = 0.0156250000000000
2^-7  = 0.0078125000000000
2^-8  = 0.0039062500000000
2^-9  = 0.0019531250000000
2^-10 = 0.0009765625000000
2^-11 = 0.0004882812500000

需要注意的事项:

  1. C语言的大多数实现都表示浮点数字是2的负幂之和(那么这个和本身就是乘以2的幂)
  2. 你在上面看到的模式将继续适用于2.这是因为当末端的50除以2时,它总是会产生一个末端有5的数字,而5会再向右小数一位
  3. 当你将2的负幂的任意组合求和时最小的数字将始终贡献末尾的5数字,并且该5将不会与任何在较大的数字中

所以所有具有精确表示的数字都以5结尾。然而,这并不是说每个以5结尾的数字都有一个精确的表示。例如0.385没有精确的表示,并且将不通过相等性测试。