在8位微控制器上,我想执行以下操作:
16bit_integer = another_16bit_integer * 0.997;
尽可能少的指令。
答案 0 :(得分:4)
32位整数运算怎么样?
16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);
32位足以存储(INT16_MAX×997),对值大1000倍,然后再分为16位。
答案 1 :(得分:3)
位移通常非常快:
y = 0xFF3B * (int32_t) x >> 16;
这可能写得更好:
y = (0.997 * 0x10000) * (int32_t)x >> 16;
一个好的编译器会产生等效的输出。
如果您的整数已签名,则常量应更改为0x8000和15.
答案 2 :(得分:2)
你可能想要在那里进行一些舍入,而不是将结果截断为整数,否则操作的目的实际上是有限的。
但是既然你用这个特定的公式提出问题,就会想到你的结果集非常粗糙。对于前333个数字,结果为:another_16bit_integer-1。您可以通过以下方式对其进行近似(甚至可能是在我的头脑中未完成时):
16bit_integer = another_16bit_integer - 1 - (another_16bit_integer/334);
编辑:unsigned int,你自己处理0。
答案 3 :(得分:1)
在我的平台上(Atmel AVR 8位微控制器,运行gcc)
16bit_integer = another_16bit_integer * 0.997;
需要约26条指令。
16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);
需要大约25条指令。
答案 4 :(得分:1)
这是一种非常快速的方法来执行此操作:
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
答案 5 :(得分:0)
预先计算的查找表:
16bit_integer = products[another_16bit_integer];
答案 6 :(得分:0)
预先计算的查找表:
16bit_integer = products[another_16bit_integer];
这在AVR上不会那么好用,16位地址空间将会耗尽。
答案 7 :(得分:0)
由于您使用的是8位处理器,因此您可能只能处理16位结果,而不能处理32位结果。为了减少16位溢出问题,我会重申这样的公式:
result16 = operand16 - (operand16 * 3)/1000
这将给出高达21845的无符号整数或高达10922的有符号整数的精确结果。我假设处理器可以进行16位整数除法。如果你不能那么你需要艰难地进行分工。乘以3可以通过简单的移位来实现。如果不存在乘法指令或者乘法仅适用于8位操作数,则添加。
在不知道确切的微处理器的情况下,无法确定这样的计算需要多长时间。
答案 8 :(得分: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条指令。
Atmel AVR是一个RISC芯片,所以计数指令是一个有效的比较。