为什么在Java float比较中使用Float.floatToIntBits()?

在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; } 

我想知道float int位转换函数的用途是什么,这里。 这是否提供了解决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必须是整数。

可以在Joshua Bloch的Effective Java中找到解释: floatFloat需要特殊处理,因为存在-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的值为false。 如果f1表示+ 0.0f而f2表示-0.0f,反之亦然,则相等测试的值为false,即使0.0f == – 0.0f的值为true。

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

Double.Nan(Not-a-number)在比较时是一个特殊值:

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

这打印:

 false true 

我不知道100%,但很可能他们试图绕过NaN!= NaN问题。 如果您的浮动恰好是NaN,则无法与任何内容进行比较,因为结果始终为false。 比较intBits会给你NaN == NaN。

    Interesting Posts