测试浮点相等。 (FE_FLOATING_POINT_EQUALITY)

我在ANT脚本中使用了一个findbugs,我无法弄清楚如何解决我的两个错误。 我已阅读文档,但不明白。 以下是我的错误以及与之相关的代码:

错误1:测试浮点相等性。 (FE_FLOATING_POINT_EQUALITY)

private boolean equals(final Quantity other) { return this.mAmount == convertedAmount(other); } 

错误2:EQ_COMPARETO_USE_OBJECT_EQUALS

 public final int compareTo(final Object other) { return this.description().compareTo(((Decision) other).description()); } 

我已经阅读了ComparesTo问题的文档

强烈建议,但并非严格要求(x.compareTo(y)== 0)==(x.equals(y))。 一般来说,任何实现Comparable接口并且违反此条件的类都应该清楚地表明这一事实。 推荐的语言是“注意:此类具有与equals不一致的自然顺序。”

以及有关浮点平等的文档

此操作比较两个浮点值是否相等。 由于浮点计算可能涉及舍入,因此计算的浮点值和双精度值可能不准确。 对于必须精确的值,例如货币值,请考虑使用固定精度类型,例如BigDecimal。 对于不必精确的值,请考虑比较某些范围内的相等性,例如:if(Math.abs(x-y)<.0000001)。 请参阅Java语言规范,第4.2.4节。

我不明白。 有人可以帮忙吗?

问题1:

对于FE_FLOATING_POINT_EQUALITY问题,您不应该直接使用==运算符比较两个浮点值,因为由于微小的舍入错误,即使条件value1 == value2不成立,值也可能在语义上与您的应用程序“相等” 。

要解决此问题,请按以下方式修改代码:

 private boolean equals(final Quantity other) { return (Math.abs(this.mAmount - convertedAmount(other)) < EPSILON); } 

其中EPSILON是您应在代码中定义的常量,表示应用程序可接受的小差异,例如.0000001。

问题2:

对于EQ_COMPARETO_USE_OBJECT_EQUALS问题:强烈建议在x.compareTo(y)返回零的任何地方, x.equals(y)应为true 。 在您的代码中,您已经实现了compareTo ,但是您没有覆盖equals ,因此您inheritance了Objectequals实现,并且不满足上述条件。

为了解决这个问题,在类中重写equals (也许是hashCode ),这样当x.compareTo(y)返回0时, x.equals(y)将返回true

对于浮点警告,您应该记住浮点数是一种不精确的类型。 给出的标准参考(也许值得一读)是:

每个计算机科学家应该知道的关于浮点运算的大卫戈德伯格。

因为浮点数不是精确值 – 即使它们在向上舍入到几位小数时看起来相同 – 它们可能会略有不同,并且无法匹配。

Comparable接口期望其实现者具有某种行为; 警告告诉你你没有遵守这一点,并提供建议的行动。

我不同意上面的答案。 等于和比较在浮点比较中引入epsilons是错误的地方。

浮点值可以通过equals和compareTo精确比较,只需使用“==”运算符即可。
如果您的应用程序使用由计算结果的浮点数,则需要将这些值与epsilon方法进行比较,它应该仅在需要此值的位置进行。 例如,在数学线交叉法中。
但不是等于和比较。

这个警告非常误导。 这意味着比较两个浮点数,其中一个是计算结果,可能会产生意外结果。 然而,通常这种浮动,比较,不是计算的结果,如

 static final double INVALID_VALUE = -99.0; if (f == INVALID_VALUE) 

其中f用INVALID_VALUE初始化,在java中总是能完美地工作。 但是,findbugs和sonarcube仍然会抱怨。

所以只需在findbugs中添加一个忽略filter,假设你有两个类MyPoint2D和Myrectangle2D