浮動小数点値が等しいかどうかを比較する場合、2つの異なる方法があります。
C#(にIEEE浮動小数点型に内蔵float
し、double
IEEEのためのセマンティクス従う)==
及び!=
(等リレーショナル演算子<
)が、ための反射性を確保しobject.Equals
、IEquatable<T>.Equals
(およびCompareTo
)。
ここで、float
/の上にベクター構造体を提供するライブラリについて考えますdouble
。このようなベクトル型は過負荷になり==
/ !=
およびオーバーライドobject.Equals
/ IEquatable<T>.Equals
。
何皆に同意すると、そのある==
/ !=
IEEEセマンティクスに従ってください。問題は、そのようなライブラリーがEquals
再帰的な方法で、またはIEEEセマンティクスに一致する方法で(等価演算子とは別の)メソッドを実装するかどうかです。
のIEEEセマンティクスを使用するための引数Equals
:
- IEEE 754に準拠
SIMD命令を利用できるため、(おそらくはるかに)高速です。
私は、スタックオーバーフローについて、SIMD命令を使用して再帰的等式をどのように表現するか、およびそれらのパフォーマンスへの影響について、別の質問をしました。浮動小数点の等値比較のためのSIMD命令
更新: 3つのSIMD命令を使用して効率的に再帰的等式を実装できるようです。
のドキュメントで
Equals
は、浮動小数点を使用する場合に再帰性は必要ありません。次のステートメントは、Equals(Object)メソッドのすべての実装に当てはまる必要があります。リストには、
x
、y
、およびz
nullではないオブジェクト参照を表します。x.Equals(x)
true
浮動小数点型を含む場合を除いて、を返します。ISO / IEC / IEEE 60559:2011、情報技術-マイクロプロセッサシステム-浮動小数点演算を参照してください。floatを辞書のキーとして使用している場合は、罪の状態にあり、正常な動作を期待するべきではありません。
再帰的であるという主張:
それはを含む既存のタイプと一致だ
Single
、Double
、Tuple
とSystem.Numerics.Complex
。Equals
再帰的ではなく、IEEEに従うBCLの前例は知りません。カウンターの例としてはSingle
、Double
、Tuple
とSystem.Numerics.Complex
。Equals
主に、反射性に依存するコンテナと検索アルゴリズムで使用されます。これらのアルゴリズムでは、動作を妨げる場合、パフォーマンスの向上は重要ではありません。パフォーマンスの正確さを犠牲にしないでください。- これは、すべてのハッシュベースのセットや辞書、壊れる
Contains
、Find
、IndexOf
さまざまなコレクション/ LINQ、セットベースのLINQの操作(上Union
、Except
データが含まれている場合など)NaN
の値を。 IEEEセマンティックが受け入れられる実際の計算を行うコードは、通常、具象型で機能し、
==
/!=
(またはより可能性の高いイプシロン比較)を使用します。ジェネリック演算が必要なため、現在ジェネリックを使用して高性能計算を作成することはできませんが、これらはインターフェース/仮想メソッドを介して利用できません。
したがって、遅い
Equals
メソッドはほとんどの高性能コードに影響を与えません。IEEEセマンティクスが必要な場合、またはパフォーマンス上の利点が必要な場合に、
IeeeEquals
メソッドまたはを提供するIeeeEqualityComparer<T>
ことができます。
私の意見では、これらの議論は再帰的な実装を強く支持しています。
MicrosoftのCoreFXチームは、そのようなベクトル型を.NETに導入することを計画しています。私とは異なり、彼らは主にパフォーマンス上の利点のために、IEEEソリューションを好みます。このような決定は最終リリース後も変わらないので、大きな間違いだと私が信じていることについてコミュニティからフィードバックを得たいと思います。
float
/ double
と他のいくつかの型のために、==
そしてEquals
すでに異なっています。既存のタイプとの不整合は==
、それらの間の不整合よりもさらに混乱Equals
し、他のタイプについては引き続き対処する必要があると思います。2)ほとんどすべての一般的なアルゴリズム/コレクションはEquals
、その機能の柔軟性(LINQおよび辞書)を使用および依存しますが、具体的な浮動小数点アルゴリズムは通常==
、IEEEセマンティクスを取得する場所で使用します。
Vector<float>
単純なfloat
やとは別の「ビースト」を考えdouble
ます。その方法では、私はそれらの基準を遵守する理由Equals
や==
オペレーターを理解できません。「フロートを辞書のキーとして使用している場合、あなたは罪の状態にあり、正気な行動を期待してはいけません」NaN
辞書に保存するとしたら、それはひどい慣習を使うことに対する彼ら自身のくだらない責任です。CoreFXチームがこれを完全に考えていなかったとは、私にはほとんど思えません。ReflexiveEquals
パフォーマンス向上のために、私はと同様のものを使用します。
==
し、Equals
異なる結果を返すでしょうが。多くのプログラマーはそうであると想定し、同じことをします。さらに-一般に、等価演算子の実装はEquals
メソッドを呼び出します。を含めることもできますIeeeEquals
が、逆の方法で-ReflexiveEquals
メソッドを含めることもできます。Vector<float>
型はで使用することができる多くのパフォーマンス・クリティカルなアプリケーション、およびそれに応じて最適化する必要があります。