比较浮点数值

9

我刚刚阅读了一份关于浮点数值比较的声明。

不应使用“==”或“!=”运算符来比较浮点数值。大多数浮点数值没有精确的二进制表示,而且具有有限的精度。

那么,比较两个浮点数值的最佳方法是什么?


你能解释一下为什么需要进行比较吗?还是你只是对那份文档感到好奇? - rjmunro
可能是如何进行浮点数比较?的重复问题。 - Magnus
3个回答

13
以下扩展方法可能有助于实现Kevin的建议:
public static bool IsEqualTo(this double a, double b, double margin)
{
    return Math.Abs(a - b) < margin;
}

public static bool IsEqualTo(this double a, double b)
{
    return Math.Abs(a - b) < double.Epsilon;
}

所以现在你只需要这样做:

if(x1.IsEqualTo(x2)) ...
if(x1.IsEqualTo(x2, 0.01)) ...

只需将IsEqualTo更改为更合适的名称,或者将默认边距更改为任何比double.Epsilon更好的值(如有必要)。


4

通常应该使用类似以下结构来比较浮点数:

if( abs((x1 - x2) < 0.001) )

你引用的警告原因是你可能有两种计算方法,如果没有舍入误差,它们可能相等,但舍入误差使它们稍微有所不同。

2
请使用 abs(x1 - x2) < 0.001 * x1 来代替。 - Alexandre C.
@Alexandre:为什么?如果您能给我们一些解释,那将会很有帮助。 - shuhalo
2
@user411768:这是因为“通常”。通常情况下,您比较相对精度而不是绝对精度。如果x1和x2的数量级为10^-6,但x1是x2的五倍大,那么您肯定不希望上述结构告诉您x1 == x2。当然,也有绝对精度正确的情况。这个主题很难。 - Alexandre C.

1
“最佳方法”取决于您想比较数字的原因。一般来说,如果您认为要检查两个浮点数是否相等,则您正在做错误的事情。
浮点数应该用于表示实际值,在词义上都是如此。这个对象与另一个对象长度相同吗?嗯,它们可能看起来长度相同,但如果您使用足够好的测量设备,您总是可以找到差异。同样,除非它们测量的是同一件事,并且已经以完全相同的方式进行处理,否则两个浮点数永远不会相等。除此之外,这只是系统中的四舍五入误差。
正如其他答案所建议的那样,您可能希望检查它们是否接近(比某个阈值更接近),但不是相等的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接