将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.