40

これら 2 つの操作が異なる値を返す理由を突き止めようとしています。

  1. Double.NaN == Double.NaN戻り値false
  2. Double.NaN.Equals(Double.NaN) 戻り値true

最初の部分には答えがありますが、2番目の部分には答えがなく、「これら2つの比較が異なる値を返すのはなぜですか」という答えはありません

4

4 に答える 4

34

明らかではないにしても、違いの理由は単純です。

等値演算子を使用する場合==は、IEEE の等値テストを使用しています。

メソッドを使用している場合はEquals(object)、 の契約を維持する必要がありobject.Equals(object)ます。このメソッド (および対応するGetHashCodeメソッド) を実装するときは、そのコントラクトを維持する必要があります。これは、IEEE の動作とは異なります。

契約が守られなかった場合、Equalsハッシュ テーブルの動作が壊れます。

var map = new Dictionary<double,string>();
map[double.NaN] = "NaN";
var s = map[double.NaN];

の場合!double.NaN.Equals(double.NaN)、辞書から値を取得することはできません!

前の文が意味をなさない場合は、ハッシュの仕組み ( 、 などで使用される) が と メソッドの両方を広範に使用し、それらの動作の保証に依存していることを理解Dictionary<T,U>してHashSet<T>ください。object.Equals(object)object.GetHashCode()

于 2013-01-22T13:00:18.330 に答える
9

の備考セクションの一番下にDouble.Equals、次の情報があります。

Equalsメソッドを呼び出して2つのDouble.NaN値が等しいかどうかをテストすると、メソッドはtrueを返します。ただし、2つのNaN値が等式演算子を使用して等式であるかどうかがテストされる場合、演算子はfalseを返します。Doubleの値が数値(NaN)でないかどうかを判断する場合は、IsNaNメソッドを呼び出すこともできます。

于 2013-01-22T12:50:04.693 に答える
3

ええと、Odedの答えは素晴らしいですが、私は何か言いたいです。

メソッドを逆コンパイルDouble.Equals()すると、次のようになります。

public bool Equals(double obj)
{
    return ((obj == this) || (IsNaN(obj) && IsNaN(this)));
}

つまり、これはDouble.NaNであり、obj=Double.NaNであるためです。

(IsNaN(obj)) and (IsNaN(this)) returns `true`.

だから基本的にそれは可能ですreturn ((obj == this) || true

これはに相当します

return ((obj == this)ですtrue

于 2013-01-22T12:59:15.350 に答える
3

Double.NaN; を調べた場合。

    // Summary:
    //     Represents a value that is not a number (NaN). This field is constant.
    public const double NaN = 0.0 / 0.0;

NaN は数値を表していないため、最初のものは false を返します。

演算の結果が未定義の場合、メソッドまたは演算子は NaN を返します。たとえば、ゼロをゼロで除算した結果は NaN です。

NaNオーバーロードされたメソッドで等価性が明示的に実装されているため、2 番目は true を返しますequals

msdn double.equalsから:

Equals メソッドを呼び出して 2 つの Double.NaN 値が等しいかどうかをテストすると、メソッドは true を返します。ただし、等値演算子を使用して 2 つの NaN 値が等しいかどうかをテストすると、演算子は false を返します。Double の値が数値 (NaN) ではないかどうかを判断する場合は、代わりに IsNaN メソッドを呼び出します。

これは、に準拠するために意図的に行われIEC 60559:1989ます。

IEC 60559:1989 によると、NaN の値を持つ 2 つの浮動小数点数が等しくなることはありません。ただし、System.Object::Equals メソッドの仕様によると、このメソッドをオーバーライドして、値が等しいセマンティクスを提供することが望ましいとされています。System.ValueType は Reflection を使用してこの機能を提供するため、Object.Equals の説明では、値の型はデフォルトの ValueType 実装をオーバーライドしてパフォーマンスを向上させることを検討する必要があると具体的に述べています。実際、System.ValueType::Equals のソース (SSCLI の clr\src\BCL\System\ValueType.cs の 36 行目) を見ると、System.ValueType の効果に対する CLR Perf チームからのコメントさえあります。 ::高速ではないに等しい。

参照: http://blogs.msdn.com/b/shawnfa/archive/2004/07/19/187792.aspx

于 2013-01-22T12:52:45.437 に答える