メインコンテンツまでスキップ

比較演算の注意点

浮動小数点数は、演算結果に微小な誤差が含まれるため、== 演算子による直接比較は予期せぬ結果を招くことがあります。本章では、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              精度が低いため大きめに設定      
金融計算(decimal1e-281e-10    精度が非常に高いため小さめに設定
科学技術計算        1e-121e-15    高精度が要求される場合          
注記

イプシロンが大きすぎると、異なる値を誤って「等しい」と判断してしまうリスクがあります。逆に小さすぎると、誤差を吸収できず false になる可能性があります。