测试浮点相等。 (FE_FLOATING_POINT_EQUALITY)

时间:2010-09-30 16:13:34

标签: java ant findbugs

我在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节。

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

3 个答案:

答案 0 :(得分:19)

问题1:

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

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

value1 == value2

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

问题2:

对于EQ_COMPARETO_USE_OBJECT_EQUALS问题:强烈建议在private boolean equals(final Quantity other) { return (Math.abs(this.mAmount - convertedAmount(other)) < EPSILON); } 返回零的任何地方,x.compareTo(y)应为x.equals(y)。在您的代码中,您实现了true,但是您没有覆盖compareTo,因此您继承了equals的{​​{1}}实现,并且不满足上述条件。

要解决此问题,请在您的班级中覆盖equals(可能还有Object),这样当equals返回0时,hashCode将返回{{1} }}

答案 1 :(得分:6)

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

David Goldberg的

What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

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

答案 2 :(得分:1)

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

浮点值可以通过equals和compareTo进行精确比较,只需使用&#34; ==&#34;运营商。
如果您的应用程序使用计算结果的浮点数,则需要将这些值与epsilon方法进行比较,它只应在需要此值的地方进行。例如,在数学线交叉法中 但不是等于和比较。

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

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

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

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

<Match>
        <OR>
            <Class name="~.*\.MyPoint2D" />
            <Class name="~.*\.MyRectangle2D" />
        </OR>
        <Bug code="FE" />
        <Justification author="My Name" />
        <Justification
            text="Floating point equals works (here)." />
    </Match>