1

以下は、許容範囲内で2倍の等価性を決定することになっているコードのテストブロックです。

double lhs_1 = 0.02;
double lhs_2 = 0.04;
double rhs = 0.03;
double tolerance = 0.01;

bool is_match_1 = (abs(lhs_1 - rhs) <= tolerance);
bool is_match_2 = (abs(lhs_2 - rhs) <= tolerance);

ただし、is_match_2はfalseになり、is_match_1はtrueになります。コンピューターに保存されている数値は目立たない値であり、連続していないことを理解しています。誰かが解決策を共有できますか?私は理にかなった範囲でテストに合格する側で誤りを犯したいと思います。現在の精度に応じてdoubleの値を1ずつインクリメントする方法はありますか(doubleのビットレイアウトに慣れていません)?この粒度の問題を考慮して、許容値をインクリメントするだけかもしれないからです。

編集:

これが実際に実装されると、ユーザーは入力と許容値を定義するので、入力する値に関係なく、期待される出力を提供しようとしています。

4

4 に答える 4

2

残念ながら、許容範囲を選択するための「適切な」ルールはありません。

「マシンイプシロン」を自由に使用できます

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_equals1つのイプシロンが「食べられ」ます。キャンセルできますが、キャンセルできます。平均して、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述語に少し似たアルゴリズムに比較子を渡します。これにより、比較のロジックをアルゴリズムにハードコーディングしないようにすることができます。

つまり、万能のルールはありません。問題に応じて選択する必要があります

于 2012-01-25T21:26:08.043 に答える
2

浮動小数点数の比較は、ここで役立つかもしれませんし、おそらく私の浮動小数点比較がうまくいかないのはなぜですか?

于 2012-01-25T21:15:08.473 に答える
0

あなたの許容範囲はすでに非常に緩いです-あなたが比較している数と比較して0.01は巨大です。0.01000001まで開くだけで大丈夫です。

于 2012-01-25T21:25:46.493 に答える
0

許容範囲を持つことの要点は、単純な等価チェックを回避することです。難しい方法を学んだばかりなので、ダブルスでは実際には機能しません。ダブルスの世界では、1+1 は 2 と等しくない場合があります (内部的には 1.99999743 のようになる可能性があるため)。

したがって、「差は許容範囲に等しい」というのは信頼できる条件ではありません。許容差は、期待される差と同じではなく、値間の実用的な差よりも 1 ~ 2 桁小さくする必要があります。したがって、lhs_2 - rhs が rhs - lhs_1 と許容範囲内で等しいかどうかを確認したい場合は、次のチェックの方が適しています。

fabs((lhs_2 - rhs) - (rhs - lhs_1)) < 0.0001
于 2012-01-25T21:24:30.837 に答える