2

簡単に言うと、10 年以上前のコードがあり、私たちと外部の顧客の両方が使用しています。シフト ウィンドウを移動するための「シフト」番号があります。整数として設計されたのは、データ内の個別の位置を調べているためです。そのため、分数移動の概念はありませんでした。現在、彼らは整数以外のシフト番号を使用できるようにしたいと考えています。補間ではなく、単純にプログラムに整数シフトを行わせますが、その境界を超えるともう少しシフトさせます。

例はもっと理にかなっているかもしれません。10 のシフトがあるとしましょう。位置は次のようになります: 0、10、20、30、40 など

代わりに、10.4 のシフトを設定できるようにしたいと考えています。したがって、シフトは次のように機能する必要があります: 0、10、20、31、41など

10.5 のシフトは、代わりに 0、10、21、31、42 などになります。

基本的に、その小数ビットを合計し、小数点を超えると、さらに 1 つシフトします。もちろん、浮動小数点演算でよくあることですが、精度の問題が発生する可能性がありますが、速度を維持したいとも考えています。単純なアプローチの 1 つは、最初に小数ビットを分離して合計し続け、その値をチェックし、1.0 に達したときに値を減らすことです。これには、私が操作をどのように考える傾向があるかに従うという利点がありますが、反復ごとに条件付きチェックが必要であり、累積エラーの通常の可能性があります。

また、小数ビットが 1.0 を超えているかどうかを確認する前に、その小数ビットを追加できる回数を事前に計算することもできます (したがって、小数ビットが 0.5 の場合は、1 回おきに確認するだけでよいことがわかります。これは 0.3 です。約 4 ごとにチェックするだけでよいことがわかっています)。

繰り返される合計を処理する通常のアプローチは、もちろんそれを乗算に置き換えることですが、ここでは、どのフレームを「もう 1 つシフト」する必要があるかを予測するので、実際の合計についてはあまり気にしません。物事は最後に一致します。

私たちが持っている典型的なタスクには、このクラスが比較的小さな要因の組み合わせで動作することが含まれます。たとえば、96.46875 のシフトで 3000 回未満反復します。ただし、この制約が有効であり続けるという保証はありません。そのため、誰かがウィンドウを 1000 万回シフトする可能性を考慮するように言われました。

何かアドバイス?

4

2 に答える 2

1

shift次のように、目的の値に最も近い double に設定し、わずかに (1 回だけ) 増やすことを検討してください。

shift = nexttoward(shift, INFINITY); // Ensure shift is above the threshold.

次に、現在の位置を計算するには、次を使用します。

result = floor(step * shift);

stepと誤差の積shiftが 1 に近づくと、値が大きくなりすぎる可能性があります。(乗算自体にもわずかな丸め誤差がある場合があります。)ただし、以下に示すように、多くのステップでは発生しません。

の誤差shiftは最大で 1.5 ULP です (10 進数からの最初の変換では .5 ULP、 では 1 ですnexttoward)。shiftが 1024 未満の場合、ULP は 2 10–52未満です。が最大で 10,000,000 の場合、誤差は 10,000,000 • 1.5 • 2 10–52step未満であり、これは約 3.41•10 –6です。そのため、不正確な結果を生成するために必要な大きさにはほど遠いままです。

shift新たに乗算するのではなく、毎回加算して累積的に結果を計算すると、追加のエラーが発生する可能性があります。これらは小さすぎてエラーが発生しない可能性がありますが、評価する必要があります。

上記の制限に達した場合、エラーをさらに軽減する方法があります。

于 2013-04-19T14:58:37.043 に答える
0

フロア機能を使用しない理由。取得したコードを確認せずに、何が機能するかを推測します

    for (int i=0; i < 3000; i++)
    {
        cout << static_cast<int>(floor(i*shift)) << '\n';
    }

このアプローチの効率性に反対する人もいるかもしれませんが、反復回数が 3000 回未満であれば問題ありません。

于 2013-04-19T14:32:54.633 に答える