簡體   English   中英

將16位整數與double相乘的最快方法是什么?

[英]What is the fastest way to multiply a 16-bit integer with a double?

在8位微控制器上,我想做以下事情:

16bit_integer = another_16bit_integer * 0.997;

盡可能少的指令。

32位整數運算怎么樣?

16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);

32位將足以存儲(INT16_MAX×997),對值的總和大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。

在我的平台上(Atmel AVR 8位微控制器,運行gcc)

16bit_integer = another_16bit_integer * 0.997;

需要大約26條指令。

16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);

需要大約25條指令。

這是一種非常快速的方法來執行此操作:

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

預先計算的查找表:

16bit_integer = products[another_16bit_integer];

預先計算的查找表:

16bit_integer = products[another_16bit_integer];

這在AVR上不會那么好用,16位地址空間將會耗盡。

由於您使用的是8位處理器,因此您可能只能處理16位結果,而不能處理32位結果。 為了減少16位溢出問題,我會重申這樣的公式:

result16 = operand16 - (operand16 * 3)/1000

這將給出高達21845的無符號整數或高達10922的有符號整數的精確結果。我假設處理器可以進行16位整數除法。 如果你不能那么你需要艱難地進行分工。 如果不存在乘法指令或者乘法僅適用於8位操作數,則可以通過簡單的移位和相加來乘以3。

在不知道確切的微處理器的情況下,不可能確定這樣的計算需要多長時間。

在我的平台上(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芯片,因此計數指令是有效的比較。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM