3

浮動小数点誤差、浮動小数点近似などについて、たくさんのことを読みました。
問題は、現実世界の問題に対する答えを読んだことがないということです。そして今日、私は現実世界の問題に出くわしました。そして、これは本当に悪いです、そして私は本当に逃げる方法を知りません.

この例を見てください:

    [TestMethod]
    public void TestMethod1()
    {
        float t1 = 8460.32F;
        float t2 = 5990;
        var x = t1 - t2;
        var y = F(x);

        Assert.AreEqual(x, y);
    }

    float F(float x)
    {
        if (x <= 2470.32F) { return x; }
        else { return -x; }
    }

xであるはず2470.32です。しかし実際には、丸め誤差により、その値は2470.32031.
ほとんどの場合、これは問題ではありません。関数は連続しており、すべて良好ですが、結果は少し値がずれています。
しかし、ここには不連続関数があり、誤差は非常に大きくなっています。テストは不連続点で正確に失敗しました。

不連続関数で丸め誤差を処理す​​るにはどうすればよいですか?

4

5 に答える 5

6

ここでの重要な問題は次のとおりです。

  • 関数は、入力値に小さな変化がある特定のケースで、出力値に大きな (そして重要な) 変化をもたらします。
  • 関数に間違った入力値を渡しています。

「丸め誤差により、[x の値] は 2470.32031 です」と書いてあります。実行する関数を記述するだけで、専門のプログラマーのチームが完全でバグのないソース コードを数秒で提供します。あなたは彼らに何を伝えますか?

あなたが提起している問題は、「この関数に間違った値 2470.32031 を渡そうとしています。正しい値が別のものであることを認識し、渡した間違った値ではなく、渡さなかった正しい値の結果を提供する必要があります。」</p>

一般に、2470.32031 が関数に渡されて 2470.32 が意図されている場合と、2470.32031 が関数に渡されて 2470.32031 が意図されている場合とを区別することができないため、この問題を解決することは不可能です。コンピューターがあなたの心を読むとは期待できません。間違った入力を渡すと、正しい出力は期待できません。

これが教えてくれることは、関数 F の内部では解決できないということです。したがって、ズームアウトして、より大きな問題を確認する必要があります。F に渡された値を改善できるかどうか (より良い方法で、より高い精度で、または補足情報を使用して計算する)、または問題の性質が、2470.32031 が渡されるときに 2470.32 が常に意図されているようなものであるかどうかを調べる必要があります。この知識は F に組み込むことができます。

于 2013-07-16T15:22:18.187 に答える
1

8460.32 の数値を丸め誤差なしで正確にする必要がある場合は、丸め誤差なしで基数 10 の小数を表すために明示的に作成された .NET Decimal型を調べることができます。彼らがその魔法をどのように実行するかは、私を超えています。

float はおそらくどこかから来ており、それを Decimal 型にリファクタリングするのはやりすぎかもしれませんが、依存する不連続関数にそれだけの精度が必要な場合その値には、より正確な型またはいくつかの数学的トリックが必要になります。おそらく、常に実際の数値よりも小さくなるような丸め誤差を持つ float が作成されることを常に保証する方法がいくつかありますか? そのようなものが存在するかどうかはわかりませんが、問題も解決するはずです。

于 2013-07-16T14:47:28.547 に答える
-1

私は常に、浮動小数点値を比較するときに、丸めの問題のためにわずかな誤差が必要であると想定しています。あなたの場合、これはテスト メソッドでそれほど厳密ではない値を選択することを意味する可能性があります。たとえば、非常に小さなエラー定数を定義し、その値を x から減算します。これに関連するSOの質問があります。

編集して、最終的な質問に適切に対処します。おそらく、不連続点で関数が正確に何を出力するかは問題ではないため、その両側でわずかにテストします。それが重要な場合、実際にできる最善のことは、その時点で関数からの 2 つの出力のいずれかを許可することです。

于 2013-07-16T14:53:36.190 に答える