将16位整数乘以double的最快方法是什么?
时间:2020-03-05 18:43:08 来源:igfitidea点击:
在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位。
回答
在我的平台上(运行gcc的Atmel AVR 8位微控制器)
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];
回答
Precomputed lookup table:
16bit_integer = products[another_16bit_integer];
这在AVR上效果不佳,16位地址空间将被耗尽。
回答
由于我们使用的是8位处理器,因此我们可能只能处理16位结果,而不能处理32位结果。为了减少16位溢出问题,我将重述公式,如下所示:
result16 = operand16 - (operand16 * 3)/1000
对于不超过21845的无符号整数或者不超过10922的有符号整数,这将给出准确的结果。我假设处理器可以执行16位整数除法。如果不能,则需要进行困难的划分。如果不存在乘法指令,或者如果乘法仅适用于8位操作数,则可以通过简单的移位和加法来乘以3.
如果不知道确切的微处理器,就无法确定这种计算将花费多长时间。
回答
On my platform ( Atmel AVR 8-bit micro-controller, running gcc )
16bit_integer = another_16bit_integer * 0.997;
Takes about 26 instructions.
16bit_integer = (int16_t) (another_16bit_integer * (int32_t) 997 / 1000);
Takes about 25 instructions.
Atmel AVR是RISC芯片,因此计数指令是有效的比较。
回答
我们可能打算在其中进行四舍五入,而不是将结果截断为整数,否则操作的目的确实受到限制。
但是,由于我们使用该特定公式提出了问题,因此我想到了结果集确实很粗糙。对于前333个数字,结果为:another_16bit_integer-1. 我们可以使用类似以下内容的方法(甚至可能是完全正确的方法,在我的脑海中不做):
16bit_integer = another_16bit_integer - 1 - (another_16bit_integer/334);
编辑:unsigned int,并且我们自己处理0。
回答
位移通常非常快:
y = 0xFF3B * (int32_t) x >> 16;
最好这样写:
y = (0.997 * 0x10000) * (int32_t)x >> 16;
一个好的编译器将生成等效的输出。
如果整数是带符号的,则常量应更改为0x8000和15.