8 ビット マイクロ コントローラでは、次のことを行いたいと考えています。
16bit_integer = another_16bit_integer * 0.997;
可能な限り少ない数の命令で。
8 ビット マイクロ コントローラでは、次のことを行いたいと考えています。
16bit_integer = another_16bit_integer * 0.997;
可能な限り少ない数の命令で。
32 ビットの整数演算はどうですか?
16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);
(INT16_MAX × 997) を格納するには 32 ビットで十分です。1000 倍の値を合計してから、16 ビット スケールに割り戻します。
ビットシフトは通常非常に高速です。
y = 0xFF3B * (int32_t) x >> 16;
これはおそらく次のように書く方が良いでしょう:
y = (0.997 * 0x10000) * (int32_t)x >> 16;
優れたコンパイラは同等の出力を生成します。
整数が符号付きの場合、定数は0x8000および15に変更する必要があります。
結果を整数に切り捨てるのではなく、丸めを行うことを意図している可能性があります。そうしないと、操作の目的が実際に制限されます。
しかし、その特定の式で質問したので、結果セットが本当に粗いことがわかりました。最初の333個の数値の場合、結果は次のようになります:another_16bit_integer-1。あなたはそれを次のようなもので概算することができます(私の頭の中で実行されていない場合でも、おそらく正確に):
16bit_integer = another_16bit_integer - 1 - (another_16bit_integer/334);
編集:unsigned int、そしてあなたはあなた自身で0を扱います。
この操作を行うための非常に高速な方法は次のとおりです。
a = b * 0.99609375;
それはあなたが望むものに似ていますが、はるかに高速です。
a = b;
a -= b>>8;
または、PICなどのリトルエンディアンシステムでのみ機能するトリックを使用すると、さらに高速になります。
a = b;
a -= *((int8*)((&b)+1));
私の頭のてっぺんから、これはPIC18の次のアセンブラに帰着します。
; a = b
MOVFF 0xc4, 0xc2
NOP
MOVFF 0xc5, 0xc3
NOP
; a -= *((int8*)((&b)+1));
MOVF 0xc5, w
SUBWF 0xc2, f
BTFSC STATUS, C
DECF 0xc
私のプラットフォーム ( Atmel AVR 8 ビット マイクロコントローラー、 gcc を実行)
16bit_integer = another_16bit_integer * 0.997;
約26命令かかります。
16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);
約25命令かかります。
事前計算されたルックアップ テーブル:
16bit_integer = products[another_16bit_integer];
これは AVR ではうまく機能せず、16 ビットのアドレス空間が使い果たされます。
8 ビット プロセッサを使用しているため、おそらく 32 ビットの結果ではなく、16 ビットの結果しか処理できません。16 ビット オーバーフローの問題を軽減するために、式を次のように言い換えます。
result16 = operand16 - (operand16 * 3)/1000
これにより、21845 までの符号なし整数、または 10922 までの符号付き整数の正確な結果が得られます。プロセッサが 16 ビット整数除算を実行できると想定しています。できない場合は、割り算を難しい方法で行う必要があります。3 による乗算は、乗算命令が存在しない場合、または乗算が 8 ビット オペランドでのみ機能する場合、単純なシフトと加算で実行できます。
正確なマイクロプロセッサを知らなければ、そのような計算にかかる時間を決定することは不可能です。
私のプラットフォーム ( Atmel AVR 8 ビット マイクロコントローラー、 gcc を実行)
16bit_integer = another_16bit_integer * 0.997;
約26命令かかります。
16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);
約25命令かかります。
Atmel AVRは RISC チップであるため、命令のカウントは有効な比較になります。
事前計算されたルックアップ テーブル:
16bit_integer = products[another_16bit_integer];