处理浮动比较中的相等案例

时间:2016-02-22 14:34:51

标签: java

我有一些具有id和值的项目,我正在寻找最大元素。

值是浮点数/双打数,并且打破平局时我想使用ID较小的对象。

一种方法如下:

double maxValue = Double.NEGATIVE_INFINITY;
Item maxItem = null;
for (Item item : items) {
    if (item.value() > maxValue) {
        maxValue = item.value();
        maxItem = item;
    } else if (item.value() == maxValue && item.id() < maxItem.id()) {
        maxItem = item;
    }
}

然而,这包括使用浮点数进行质量比较,这是不鼓励的,在我的情况下也会在代码分析步骤中产生一个关键问题。

当然,我可以写一些东西来避免这个问题,例如使用>=进行第二次比较,但从可读性的角度来看,我未来或任何其他读者可能会怀疑它是否是一个错误。

我的问题:是否有一种方法可以很好地表达意图并避免使用==进行浮动比较来完成此任务?

2 个答案:

答案 0 :(得分:0)

在这种情况下,测试两个浮点值的相等性没有任何问题。两个float / double值可以相等,可以使用==运算符进行测试。

不建议对浮点值使用==的一个原因是,将它们与文字常量进行比较会导致意外行为,因为文字通常以十进制表示法编写,而浮点变量则以二进制表示。并非所有十进制值都可以用二进制精确表示,因此变量的值只是十进制值的近似值。例如:3.0 * 0.1 == 0.3的计算结果为false。

另一个原因是浮点值并不总是像实数一样。特别是,浮点运算不一定是可交换的(x * y == y * x)和关联的((x * y) * z == x * (y * z))。例如,(0.3 * 0.2) * 0.1 == 0.3 * (0.2 * 0.1)的计算结果为false。

但是,在您的情况下,没有理由不使用==

答案 1 :(得分:0)

你可以写一个Comparator<Item>,然后用它来找到最好的项目:

Comparator<Item> byValueAscThenIdDesc = (i1, i2) -> {
    int valueComparison = Double.compare(i1.value(), i2.value());
    if(valueComparison == 0) {
        int idComprison = Integer.compare(i1.id(), i2.id());
        return -idComparison;
    }
    return valueComparison;
};

List<Item> items = new ArrayList<>();

Item max = items.stream().max(byValueAscThenIdDesc).get();