将16位整数与double相乘的最快方法是什么?

时间:2008-08-26 04:20:00

标签: c microcontroller

在8位微控制器上,我想执行以下操作:

16bit_integer = another_16bit_integer * 0.997;

尽可能少的指令。

9 个答案:

答案 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芯片,所以计数指令是一个有效的比较。