実行時に次の計算を実行する C 関数を作成しようとしています。
分子/分母
どこ:
分子は前の計算結果であり、常に正であり、分母より大きい
と、
分母は (1 <= 分母 <= 64) です。
実行時の計算は高速である必要があります。つまり、最小サイクルである必要があるため、除算演算子は問題外です。再帰減算とビットごとの長い除算を調べましたが、別の解決策を見つけようとしています。
ヘルプはありますか?
実行時に次の計算を実行する C 関数を作成しようとしています。
分子/分母
どこ:
分子は前の計算結果であり、常に正であり、分母より大きい
と、
分母は (1 <= 分母 <= 64) です。
実行時の計算は高速である必要があります。つまり、最小サイクルである必要があるため、除算演算子は問題外です。再帰減算とビットごとの長い除算を調べましたが、別の解決策を見つけようとしています。
ヘルプはありますか?
これは、1 つの乗算と 1 つのシフトを使用する 1 つのアイデアです。したがって、ほとんどのシステムで除算よりも高速になります。分子が 768,000,000 ~= 30 ビットで最高になるので、32 ビット ワードには十分なスペースが残っていないため、64 ビットの乗算を使用する必要があります。
主なアイデアは、次の事実を利用することです。
x / y == (x * k) / (y * k)
2 の累乗で割ることは、単純で高速なビット シフトです。
したがって、特定の例を選ぶために、 and を仮定x = 700,000,000
しy = 47
ます (したがって、正しい商は 14,893,617 です)。丸め誤差を避けるために、シフトは可能な限り最大の分子のサイズである 30 ビットにほぼ等しい必要があります。k
に最も近い近似値を与えるy * k = 2^30
の値を見つけますk = 22845571
。この場合です。それからx * k = 0x38D08C4CE6F500
。これを 30 ビットシフトする0xE34231 = 14,893,617
と、予想される商が得られます。商で 1 ずれることが許容されない限り、丸めの目的で分子/分母のいくつかの組み合わせに対して 1 ~ 2 ビットを追加する必要がある可能性があります。
次に、可能な分母ごとに適切な乗数を使用してルックアップ テーブルを作成します。
編集: 以下のコメントで指摘されているように、k = (2^30 + y - 1) / y
単にk = round(2^30 / y)
.
大きい @ss テーブルは、小さい数の場合に機能します。
unsigned int divTable[kMaxNumerator][64] = {...}
可能な各分割の値をそこに入れる場所。特定のサイズを超えるとあまり実用的ではありませんが、含まれているケースでは機能し、昔はテクスチャ マッピングの一般的な解決策でした:)それからあなたのコメントを読んで、あなたが 768,000,000 の範囲にいることがわかりました。かなりの精度の低下を処理できます。