1

だから私は同じことをするべき2つの機能を持っています

float ver1(float a0, float a1) {
    float r0 = a0 - a1;
    if (abs(r0) > PI) {
        if (r0 > 0) {
            r0 -= PI2;
        } else {
            r0 += PI2;
            }
    }
    return r0;
}

float ver2(float a0, float a1) {
    float a2 = a1 - PI2;

    float r0 = a0 - a1;
    float r1 = a0 - a2;

    if (abs(r0) < abs(r1)) {
        return r0;
    }
    if (abs(r0) > abs(r1)) {
        return r1;
    }

    return 0;
}

注: PI と PI2 は、pi と 2*pi の float 定数です。

たとえば、0.28605145 と 5.9433694 をフィードすると、最初の結果は 0.62586737 になり、2 番目の結果は 0.62586755 になり、何が原因なのかわかりません。

結果がどうあるべきかを手動で計算すると、2番目の答えが正しいことがわかります。この関数は 2D 物理シミュレーションで使用しますが、最初の答え (間違った答え) がそこで機能し、2 番目の答え (正しい答え) があらゆる種類のクレイジーな動作をするというのは本当に奇妙なことです。未知の情報源からのこのような小さな違いと、これほど大きな効果:|

とにかく、この時点でマトリックスに切り替えますが、この奇妙な状況に興味を持ちました。何が起こっているのか知っている人はいますか?

4

3 に答える 3

2

float通常、精度は約 24 ビット、つまり小数点以下約 7 桁です。

r0+PI2同じ大きさの 2 つの数値 (最初の数値とa1-PI22 番目の数値) を減算しているため、重要度が失われています。結果の最上位ビットのいくつかがゼロであるため、差を表すビットが少なくなります。そのため、答えは小数点以下約 6 桁までしか一致しません。

より高い精度が必要な場合は、doubleまたは 32 ビット以上の固定小数点表現が よりも適している可能性がありますfloatGMPなど、必要な精度で数値を表すことができる任意精度のライブラリもありますが、算術演算は組み込み型よりも大幅に遅くなります。

于 2012-09-14T10:54:08.423 に答える
-1

浮動小数点数は数学的な実数のようには振る舞いません。合計が 2 になるたびに「エラー」が発生する可能性があります。したがって、1 つの例だけを理由に、最初の例を正しく、2 番目の例を正しくないとは言いません。エラーを小さく保ちたい場合は、フロートで行うすべてのアクションに注意する必要があります。

数値の絶対値が同じ範囲内にある場合、一般にエラーは小さくなります。また、範囲が異なる場合、誤差は大きくなる傾向があります。

たとえば、めったに10000000.0 + 0.1 - 10000000.0ありません0.1

入力の範囲がわかっている場合は、コードを調整してエラーを減らすことができます。

于 2012-09-14T09:55:22.020 に答える
-1

整数でのみ機能するため、fabs()代わりに関数を使用する必要があります。浮動小数点で使用すると、奇妙で​​間違った結果が得られます。abs()abs()abs()

于 2012-09-14T09:47:00.907 に答える