JetBrains Rider 2024.1 ヘルプ

コード検査: 浮動小数点数の等価比較

==/!= 演算子を使用して浮動小数点数を比較することは、一般的には悪い考えです。浮動小数点値は本質的に不正確であり、正確に等しいかどうかを比較することは、ほとんどの場合、望ましいセマンティクスではありません。==/!= 演算子による比較では、浮動小数点値の表現がまったく同じであるかどうかがチェックされます。これは、精度の低下を伴う算術演算を実行する場合はほとんどありません。例: 2 つの簡単な算術演算を実行しましょう —

  • 0.1 11 回を追加

  • 0.111 を乗算する

— そして、それらの浮動小数点の結果が等しいかどうかを確認します。

double add = 0; for (int i = 1; i <= 11; i++) { add += 0.1; } double multiply = 0.1 * 11; Console.WriteLine(add == multiply); // false

テスト実行では、add = 1.0999999999999999multiply = 1.1000000000000001 を取得します(ランタイムが異なると結果が異なる可能性があります)。== オペレーターは false との比較を評価します。

この種の比較を正しく行うには、許容値、つまり結果が意図した値からどれだけ逸脱できるかを示す値を指定する必要があります。JetBrains Rider は、比較を Math.Abs([expression]) < [tolerance] として自動的に書き換えるのに役立ちます。tolerance 値は、実行する計算の精度に依存します。この例では、0.000000001 の許容誤差に安全に依存できます。

double add = 0; for (int i = 1; i <= 11; i++) { add += 0.1; } double multiply = 0.1 * 11; var tolerance = 0.000000001; Console.WriteLine(Math.Abs(add - multiply) < tolerance); // true

このインスペクションは、ゼロ以外の値が予期される場合に「まだ初期化されていない値」または「値が存在しない」ことを表す 0+Infinity-InfinityNaN など、「マーカー値」としてよく使用される一部の値を無視することに注意してください。

ただし、これを行うためのより良い方法は、null 値を持つ double? タイプです。