使用整数分数

时间:2018-01-03 07:44:07

标签: compiler-optimization avr bit-shift avr-gcc linear-interpolation

我在Atmega328上玩直接数字合成波表。

给定8位小数值F和两个8位值A,B,计算A和B之间的线性插值的最有效方法是什么?我可以想到两种方法:

备选方案1: 插值= ((A << 8) + (B - A) * F) >> 8 (仅当B&gt; = A时才会起作用,但我可以将其包装在if / else中,如果A&gt; B则交换A和B)

备选方案2: 插值= A + (B - A) * (F / 256)

我选择哪一个或者编译器是否会以相同的方式优化它们是否有效?

是否有更好的方法不涉及乘法或除法?

编辑:将alternative 2中的分母从255更改为256

1 个答案:

答案 0 :(得分:0)

假设

  • F每个计数为1/256(并且不能完全表达1)
  • ABFuint8_t

线性插值可以是

uint8_t I = A + (uint8_t)(((int16_t)(B-A) * F) >> 8)

如果您希望255表达1.0,那么您必须除以255而不是移位,但我想我会以不同的方式处理one case。例如,对F使用16位并检查高字节,然后使用上面的公式与低位字节(如果小于1)。

以上几行与您的备选行几乎完全相同,但由于AB为8位,因此插值结果不能超过8位范围,因此可以使用uint8_t完成添加。 / p>

由于第二个被乘数(A)始终为零,因此您的备选方案2始终会获得F/256