3

A*B可能な限り精度を保ちながら、16ビットの固定小数点で乗算しようとしています。A符号なし整数範囲で16ビットであり、B1000で除算され、常にとの間0.001です9.999。私がそのような問題に対処してからしばらく経ちました、それで:

  • A*B/100032ビット変数に移動してから16ビットに戻すだけで実行できることはわかっています
  • それより速くしたい
  • 32ビットに移行せずにすべての操作を実行したい(16ビットの乗算しかないため)

それを行う簡単な方法はありますか?

編集:A0から4000の間になるので、すべての可能な結果も16ビット範囲になります。

編集:ユーザーから来て、マスクにB桁ごとに設定します。そのため、操作はです。X.XXX/1000

4

1 に答える 1

3

いいえ、32ビットに移動する必要があります。一般に、2つの16ビット数の積は常に32ビット幅の結果をもたらします。

16ビットマシンのほとんどの乗算命令には、結果を32ビット整数として直接返すオプションがあるため、作業中のCPUのCPU命令セットを確認する必要があります。

これは次の理由で大いに役立ちます。

short testfunction (short a, short b)
{
  int A32 = a;
  int B32 = b;

  return A32*B32/1000
}

コンパイラに32ビット*32ビットの乗算を強制します。お使いのマシンでは、これは非常に遅いか、16ビット乗算のみを使用して複数のステップで実行される可能性があります。

少しのインラインアセンブリ、またはさらに優れたコンパイラ組み込み関数を使用すると、処理速度が大幅に向上する可能性があります。

このような組み込み関数を持つTexasInstrumentsC64x+DSPの例を次に示します。

short test (short a, short b) 
{
  int product = _mpy (a,b); // calculates product, returns 32 bit integer
  return product / 1000;
}

別の考え:あなたは1000で割っています。それはあなたの選択で一定でしたか?固定小数点数のベースとして2の累乗を使用する方がはるかに高速です。1024が近いです。どうしてですか:

  return (a*b)/1024 

代わりは?コンパイラーは、右シフトを10ビット使用することでこれを最適化できます。これは、逆数の乗算トリックを実行するよりもはるかに高速である必要があります。

于 2010-07-18T19:24:42.540 に答える