[英]What is the correct way to convert 2 bytes to a signed 16-bit integer?
[英]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.