3

以下のC関数の違いを教えてください。

static int mandel(float c_re, float c_im, int count) {
    float z_re = c_re, z_im = c_im;
    int i;
    for (i = 0; i < count; ++i) {
        if (z_re * z_re + z_im * z_im > 4.f)
            break;

        float new_re = z_re*z_re - z_im*z_im;
        float new_im = 2.f * z_re * z_im;
        z_re = c_re + new_re;
        z_im = c_im + new_im;
    }

    return i;
}

そして、次の

static int mandel(float c_re, float c_im, int count) {
    float z_re = c_re, z_im = c_im;
    int i;
    for (i = 0; i < count; ++i) {
        if (z_re * z_re + z_im * z_im > 4.f)
            break;

        float new_im = 2.f * z_re * z_im;
        z_re = c_re + z_re*z_re - z_im*z_im;//I have combined the statements here and removed float new_re
        z_im = c_im + new_im;
    }

    return i;
}

コードの変更については、私のコメントを参照してください。関数は、一部の入力に対して異なる値を返します。2 つのステートメントを組み合わせたためにフロートがずれていますか?

4

2 に答える 2

4

数学では、2 つのステートメントは同等です。ただし、コンピューター ハードウェアではそうでない場合があります。

初期結果 (new_re) が丸められてから c_re に追加されるため、丸めエラーが発生する可能性があります。

ニクラスが言及しているように:

中間値はより高い精度で保存されます

したがって、new_re の結果は、new_re に格納されるときにいくつかの浮動小数点を失う可能性がありますが、中間値が c_re に追加される場合、c_re の小さな値と new_re 計算の下位の重要な値が組み合わされて、最終結果に寄与する可能性があります。

于 2012-10-11T05:42:48.973 に答える
1

数式を評価する場合、CまたはC ++コンパイラによって生成されたコードは、より高い精度で中間結果を保持できます。

たとえば、x86コンピュータでは、CおよびC ++のdouble値は通常64ビットのIEEE754浮動小数点数ですが、数学プロセッサスタックは計算を行うときに値ごとに80ビットを使用します。

つまり、計算の正確な結果は、一時的なものがメモリ内のどこに格納され、代わりにfpスタックのどこに保持されたかによって異なります。通常、一時的な精度は格納された値の精度よりも高いため、これは問題ではありません...ただし、計算は浮動小数点の予想される丸め規則に正確に沿って設計されている可能性があるため、これは常に当てはまるとは限りません。

コンパイラーは、数学の評価を厳密にするように、または最適化を支援するためにそれらを非常に自由にできるようにするための特別なフラグを提供することにも注意してください(ローカル変数への格納操作の無視や理論的な数学同等バージョンへの操作の書き換えを含む)。今日のデフォルトは、パフォーマンスを損なうため、多くの場合、ある程度自由で、それほど厳密ではありません。

于 2012-10-11T05:57:09.967 に答える