比較演算の注意点
浮動小数点数は、演算結果に微小な誤差が含まれるため、== 演算子による直接比較は予期せぬ結果を招くことがあります。本章では、C# における浮動小数点数の比較演算の注意点と、実務で使える安全な比較関数の設計方法について解説します。
浮動小数点数の ==
比較が危険な理由
浮動小数点数は、内部的に近似値として格納されるため、見た目には同じ値でも == 比較がfalse
を返すことがあります。
double a = 0.1 + 0.2;
double b = 0.3;
Console.WriteLine(a == b); // False
Console.WriteLine(a); // 0.30000000000000004
このような誤差は、IEEE 754に基づく浮動小数点表現の限界によるものです。演算結果が期待値と微妙に異なるため、浮動小数点数の == 比較は信頼できません。
許容誤差(イプシロン)を用いた比較手法
前述のように、浮動小数点数の比較においては、== 演算子による厳密な一致判定は信頼できません。これは、浮動小数点数が内部的に近似値として格納されるため、演算結果に微小な誤差が含まれるからです。
この問題を回避するために用いられるのが、許容誤差(epsilon) を使った比較手法です。これは、「2つの値の差がある小さな値(イプシロン)未満であれば、等しいとみなす」という考え方です。
bool AreClose(double x, double y, double epsilon = 1e-10)
{
return Math.Abs(x - y) < epsilon;
}
double a = 0.1 + 0.2;
double b = 0.3;
Console.WriteLine(AreClose(a, b)); // True
このように、0.1 + 0.2 の結果は 0.3 とは完全には一致しませんが、差が非常に小さいため、実用上は「等しい」と判断できます。 この手法は、グラフィックス処理、物理シミュレーション、金融計算、統計処理など、あらゆる分野で広く使われています。実務では、比較対象の性質に応じて適切なイプシロンを選び、再利用可能な比較関数として実装しておくと便利です。
イプシロンの選び方
イプシロンの値は、比較対象のスケールや用途に応じて調整する必要があります。以下は一般的な目安です:
用途 | 推奨イプシロン値 | 備考 |
---|---|---|
一般的な double 比較 | 1e-10 | 通常の数値演算向け |
float 型の比較 | 1e-6f | 精度が低いため大きめに設定 |
金融計算(decimal ) | 1e-28 〜 1e-10 | 精度が非常に高いため小さめに設定 |
科学技術計算 | 1e-12 〜 1e-15 | 高精度が要求される場合 |
注記
イプシロンが大きすぎると、異なる値を誤って「等しい」と判断してしまうリスクがあります。逆に小さすぎると、誤差を吸収できず false になる可能性があります。