20

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のfloat比較の不正確さの問題を回避する方法を提供しますか(それが可能である場合でも)?それともまったく別のものですか?それがイプシロンアプローチの代替であるかどうか疑問に思っています:

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は整数でなければなりません。

4

3 に答える 3

23

説明はJoshuaBlochのEffectiveJavafloatにあります。正の無限大と負の無限大Floatが存在するため、特別な処理が必要です。そのため、Sun JVMは次のようになります(6u21)。-0.0NaNFloat.equals()

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

したがって、いいえ、Math.abs()イプシロンを使用することは適切な代替手段ではありません。Javadocから:

f1とf2の両方がFloat.NaNを表す場合、Float.NaN == Float.NaNの値がfalseであっても、equalsメソッドはtrueを返します。f1が+0.0fを表し、f2が-0.0fを表す場合、またはその逆の場合、0.0f ==-0.0fの値がtrueであっても、等しいテストの値はfalseになります。

そのため、Eclipseの自動生成されたコードがそれを行います。

于 2010-09-08T13:17:25.823 に答える
10

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 
于 2010-09-08T13:14:11.427 に答える
3

100%はわかりませんが、おそらく彼らはNaN!=NaNの問題を回避しようとしています。フロートがたまたまNaNである場合、結果は常にfalseであるため、何とも比較できません。intBitsを比較すると、NaN==NaNが得られます。

于 2010-09-08T13:24:21.283 に答える