0

固定小数点 15.16 の数値を乗算およ​​び除算するアルゴリズムを探しています。

私はすでに足し算と引き算をしています。それらは簡単でした-単純な32ビットの加算と減算。乗算と除算を使用して、多くの三角関数と指数/対数関数を追加することもできます。そして、私のライブラリには逆数関数があり、それを使用して除算を実装できるため、乗算だけで処理できると思いますa * (1/b) = a / b。ただし、基数を無視するため、32 ビットの乗算は機能しません。

私は 16 ビットのマイクロコントローラーで作業しているので、プロセッサーで約 4 サイクルかかる 32 ビット以上の乗算は避けたいと考えています。重要ではありませんが、浮動小数点演算を置き換えようとしているだけです。

結果をシフトまたは回転する必要があると聞いたことがありますが、これがどのように役立つか、具体的にどのようにシフトするかはわかりません。任意の提案や助けをいただければ幸いです!

4

3 に答える 3

5

このように考えてください: あなたの番号 ab は (ab * 65536) として表されます

ab * cd を掛けると、得られる値は (ab * 65536) * (cd * 65536) なので、これを正しい表現に戻すには、65536 で割る必要があります。

ab / cd を割ると、得られる値は (ab * 65536) / (cd * 65536) になるため、これを正しい表現に戻すには、65536 を掛ける必要があります。結果で可能な限り多くのビット。

もちろん、プロセッサ上でより高速な場合は、(<< 16) を (* 65536) に置き換えることができます。同様に、(/ 65536) を (>> 16) に置き換えることができます。

ab * cd は次のとおりです。

uint32_t result_low = (b * d);
uint32_t result_mid = (a * d) + (b * c);
uint32_t result_high = (a * c); 
uint32_t result = (result_high << 16) + result_mid + (result_low >> 16)
于 2011-01-22T18:30:58.087 に答える
2

最初の理論: 符号付きの数値を仮定すると、Q15.16 に別の Q15.16 を掛けると、Q(15+15+1).(16+16) = Q31.32 の数値が得られます。したがって、結果を保持するには 64 ビット整数変数が必要です。

コンパイラに 64 ビットの整数型がある場合は、それを使用して、16 ビット CPU で 32 ビット x 32 ビットの乗算を実行する方法をコンパイラに判断させます (これがコンパイラの目的です)。

int32_t a_15q16, b_15q16;
int64_t res_31q32 = (int64_t)a_15q16 * (int64_t)b_15q16;

その後、Q31.32 の結果をどうするかは、アプリケーションによって異なります。

なぜ結果に 30 ではなく 31 の整数が必要なのか疑問に思うかもしれません。実際、追加のビットは、-2^15 を -2^15 で乗算する場合にのみ必要です。オペランドが同時に -2^15 に等しくならないことが保証されている場合、Q30.32 の結果を想定できます。

コンパイラが 64 ビット整数をサポートしているかどうかを確認するには、コンパイラのマニュアルを参照する必要がある場合があります。これが C99 コンパイラの場合は、stdint.h ヘッダーに int64_t 型があるかどうかを確認してください。

于 2011-01-23T20:36:30.733 に答える
0

乗算は、64 ビットの乗算で簡単に実行できます(a * b) >> 16。同様に、除算は 64 ビットで簡単に実行できます(a << 16) / b。丸め/エラーの要件によっては、出力の最後のビットを正しくするために、少し複雑にする必要がある場合があります。

于 2011-01-22T18:27:03.930 に答える