【问题标题】:Why use Float.floatToIntBits() in Java float comparisons?为什么在 Java 浮点比较中使用 Float.floatToIntBits()?
【发布时间】:2010-09-08 12:56:23
【问题描述】:

在JBox2d中,Vec2.equals()存在如下代码:

@Override
public boolean equals(Object obj) { //automatically generated by Eclipse
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Vec2 other = (Vec2) obj;
    if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x))
        return false;
    if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y))
        return false;
    return true;
}

我想知道 floatint 位转换函数的用途是什么,在这里。这是否提供了一种方法来解决 Java 的浮点比较不准确问题(如果可能的话)?还是完全是别的东西?我想知道它是否可以替代 epsilon 方法:

if (Math.abs(floatVal1 - floatVal2) < epsilon)

PS。为了完整和感兴趣,这里是Vec2.hashCode()

@Override
public int hashCode() { //automatically generated by Eclipse
    final int prime = 31;
    int result = 1;
    result = prime * result + Float.floatToIntBits(x);
    result = prime * result + Float.floatToIntBits(y);
    return result;
}

仅供参考,我可以完全理解为什么在 hashCode() 中使用转换函数——哈希 ID 必须是整数。

【问题讨论】:

    标签: java vector floating-point box2d


    【解决方案1】:

    解释见Joshua Bloch's Effective JavafloatFloat需要特殊处理,因为存在-0.0NaN、正无穷大和负无穷大。这就是 Sun JVM 的 Float.equals() 看起来像这样 (6u21) 的原因:

    public boolean equals(Object obj)
    {
        return (obj instanceof Float)
               && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
    }
    

    所以,不,带有 epsilon 的 Math.abs() 不是一个好的选择。来自 Javadoc:

    如果 f1 和 f2 都代表 Float.NaN, 然后equals方法返回true, 即使 Float.NaN==Float.NaN 有 值为假。如果 f1 表示 +0.0f 而 f2 代表 -0.0f,反之亦然,等式检验有 值为假,即使 0.0f==-0.0f 值为真。

    这就是 Eclipse 的自动生成代码为您做这些的原因。

    【讨论】:

    • 也就是说,这完全优于epsilon的方法?如果是这样,我简直不敢相信我的运气。
    • 好吧,如果你能保证你不会得到任何NaNs-0.0 或无穷大,那么使用Math.abs() &lt; epsilon 可能会更快。也许吧。
    • 我从下面的 cmets 看到我弄错了这是做什么的。它解决了以特殊浮点值为中心的问题;它不处理浮动不准确 - 正如您最初在回答中所说的那样。所以忽略我的最后一个问题。
    • Math.abs() randomascii.wordpress.com/2012/02/25/… 因此,除非您实现自己的函数来计算一个好的 epsilon,否则您最好只使用 equals() ,因为它总是会给您正确的答案(对于您系统的可用精度,并且除了 -0.0f 到 0.0f)。
    【解决方案2】:

    Double.Nan(非数字)在比较时是一个特殊值:

    System.out.println(Float.NaN == Float.NaN);
    System.out.println(Float.floatToIntBits(Float.NaN) == Float.floatToIntBits(Float.NaN));
    

    打印出来:

    false
    true 
    

    【讨论】:

      【解决方案3】:

      我不知道 100%,但很可能他们正试图解决 NaN != NaN 问题。如果您的浮点数恰好是 NaN,则您无法与任何东西进行比较,因为结果总是错误的。比较 intBits 会给你 NaN == NaN。

      【讨论】:

        猜你喜欢
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        • 2011-02-23
        • 2021-05-04
        • 1970-01-01
        • 2011-08-20
        • 1970-01-01
        相关资源
        最近更新 更多