22

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

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

4

3 回答 3

19

问题1:

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

为了解决这个问题,修改你的代码如下:

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

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

问题2:

对于 EQ_COMPARETO_USE_OBJECT_EQUALS 问题:强烈建议无论x.compareTo(y)返回零,x.equals(y)都应该是true. 在您的代码中您已经实现compareTo,但您没有覆盖equals,所以您继承了equalsfrom的实现Object,并且不满足上述条件。

为了解决这个问题,在你的类中覆盖equals(也许是hashCode),这样当x.compareTo(y)返回 0 时,x.equals(y)就会返回true

于 2010-10-03T18:12:50.760 回答
6

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

大卫·戈德堡 (David Goldberg)的《每位计算机科学家都应该知道的关于浮点运算的知识》。

因为浮点数不是精确值——即使它们在四舍五入到小数点后看起来相同——它们可能会略有不同,并且无法匹配。

Comparable 接口期望其实现者有某种行为;警告是告诉您您没有遵守该规定,并提供建议的操作。

于 2010-09-30T17:28:23.567 回答
2

我不同意上面的答案。Equals 和 compareTo 是在浮点比较中引入 epsilon 的错误位置。

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

这个警告非常具有误导性。这意味着比较两个浮点数,其中至少一个是计算结果可能会产生意想不到的结果。然而,通常这样的浮动,比较,不是计算的结果,比如

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>
于 2015-04-21T13:53:21.863 回答