使用==运算符比较float/double值

Ara*_*ram 18 java floating-point

当我开始使用相等运算符比较两个浮点值时,我使用的代码审查工具会引用以下内容.什么是正确的方法以及如何做到这一点?是否有一个帮助函数(commons-*),我可以重用它?

描述

无法使用equals(==)运算符比较浮点值

说明

通过使用等式(==)或不等式(!=)运算符来比较浮点值并不总是准确的,因为舍入错误.

建议

比较两个浮点值以查看它们是否接近值.

float a;
float b;

if(a==b)
{
..
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*som 33

IBM建议使用除法而不是减法来比较两个浮点数 - 这样可以更容易地选择适用于所有输入范围的epsilon.

if (abs(a/b - 1) < epsilon)
Run Code Online (Sandbox Code Playgroud)

至于epsilon的值,我将使用此Wikipedia表中5.96e-08给出的值,或者可能是该值的2倍.

  • 如果`b == 0`怎么办? (8认同)
  • 伊克.这段代码不仅非常缓慢,而且在很多情况下也很容易出错.如果将x与(yz)进行比较,则公差需要基于y和z的大小,而不是差异的大小,并且上述代码无法将其考虑在内.x和y之间的精确相等测试通常是合适的,例如,如果计算f(x)并想知道是否应该打扰计算f(y)[或仅仅使用f(x)的值].不幸的是,确切的相等测试通常很困难,尽管`==`运算符在大多数情况下都足够好. (2认同)

Pau*_*aul 10

它希望您将它们与您需要的准确度进行比较.例如,如果您要求浮点数的前4个十进制数字相等,那么您将使用:

if(-0.00001 <= a-b && a-b <= 0.00001)
{
..
}
Run Code Online (Sandbox Code Playgroud)

要么:

if(Math.abs(a-b) < 0.00001){ ... }
Run Code Online (Sandbox Code Playgroud)

将所需精度添加到两个数字之差的位置,并将其与所需精度的两倍进行比较.

无论你怎么想都更具可读性.我自己更喜欢第一个,因为它清楚地显示了你允许的双方精度.

a = 5.43421b = 5.434205将通过所述比较


biz*_*lop 6

private static final float EPSILON = <very small positive number>;

if (Math.abs(a-b) < EPSILON)
   ...
Run Code Online (Sandbox Code Playgroud)

由于浮点为您提供了可变但无法控制的精度(也就是说,您无法设置除使用double和之间选择时的精度float),您必须选择自己的固定精度进行比较.

请注意,这不再是真正的等价运算符,因为它不是传递性的.您可以轻松获得a等于bb等于ca不等于c.

编辑:还要注意,如果a是负数且b是一个非常大的正数,减法可以溢出,结果将是负无穷大,但测试仍然有效,因为负无穷大的绝对值是正无穷大,这将更大比EPSILON.