残念ながら、許容範囲を選択するための「適切な」ルールはありません。
「マシンイプシロン」を自由に使用できます
double epsilon = std::numeric_limits<double>::epsilon()
これは最小値であり、1に加算すると、1とは異なる結果が得られます。
私は通常、公差をイプシロンの関数として記述します。良いルールはありませんが、例えばこのように比較する
bool fuzzy_equals(double a, double b)
{
static const double eps = std::numeric_limits<double>::epsilon();
return std::fabs(b - a) < 1024 * eps * std::max(a, b);
}
多くの場合うまく機能します。あなたは1024を調整することができます、私は2の累乗が好きです、しかしあなたはそうではないかもしれません。選択する実際の値は、問題によって異なります。ダブルスのイプシロンは約10^-16であるため、1024は非常に小さく、多くの場合、より大きな数が必要になります(実質的に、内部のマイナス操作を含むすべての操作でfuzzy_equals
1つのイプシロンが「食べられ」ます。キャンセルできますが、キャンセルできます。平均して、n
操作はsqrt(n) * epsilon
精度を意味するため、1024は100万回の操作後に期待される精度に対応します)。
精度がそれほど良くない他の場合、たとえば、既知の値に対して関数の最小値をテストする場合(最小値は通常、sqrt(eps)の精度までしか決定されません)、私は次のように使用します。
bool fuzzy_equals2(double a, double b)
{
static const double eps = std::numeric_limits<double>::epsilon();
return std::fabs(b - a) < 1024 * std::sqrt(eps) * std::max(a, b);
}
私はよく、、std::pow(eps, something)
またはなどの他の関数を使用します-1 / std::log(eps)
。これは、問題から導き出すことができる事前情報と、予想されるエラーによって異なります。
コード構造に関しては、機能的なアプローチを使用して、STL述語に少し似たアルゴリズムに比較子を渡します。これにより、比較のロジックをアルゴリズムにハードコーディングしないようにすることができます。
つまり、万能のルールはありません。問題に応じて選択する必要があります