为什么在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中找到解释: float
和Float
需要特殊处理,因为存在-0.0
, NaN
,正无穷大和负无穷大。 这就是为什么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。