注意 这是一个理论问题。我对我的实际代码的性能感到满意。我只是想知道是否有替代方法。
是否有技巧可以将一个整数变量值除以一个整数二次幂常量值,而不必进行实际的除法运算?
// The fixed value of the numerator
#define SIGNAL_PULSE_COUNT 0x4000UL
// The division that could use a neat trick.
uint32_t signalToReferenceRatio(uint32_t referenceCount)
{
// Promote the numerator to a 64 bit value, shift it left by 32 so
// the result has an adequate number of bits of precision, and divide
// by the numerator.
return (uint32_t)((((uint64_t)SIGNAL_PULSE_COUNT) << 32) / referenceCount);
}
我找到了很多关于如何通过一个常数进行整数和浮点数除法的技巧参考资料。例如,问题What's the fastest way to divide an integer by 3?有很多好的答案,包括其他学术和社区材料的参考。
考虑到分子是常数,并且它是2的整数次幂,是否有一种巧妙的技巧可以代替实际的64位除法;一些位运算(移位、AND、XOR等)或类似的操作?
我不想失去精度(除了由于整数舍入可能导致的半个位精度损失),因为仪器的精度取决于这个测量的精度。
“让编译器决定”不是一个答案,因为我想知道是否有技巧可用。
额外的情境信息
我正在开发一个驱动程序,用于16位数据、24位指令字微控制器。该驱动程序通过外设模块进行一些操作,以获取信号频率固定脉冲数量的参考频率脉冲计数。所需结果是信号脉冲与参考脉冲的比率,表示为无符号32位值。该函数的算术运算由我正在开发驱动程序的设备制造商定义,进一步处理结果以获得浮点实际值,但这超出了本问题的范围。我使用的微控制器具有数字信号处理器,其中包含多个可用于除法运算的操作,如果必要,我不会害怕使用它们。采用这种方法需要克服一些小挑战,如在BLDC驱动器ISR中使用DSP执行PID功能,但这并不是我不能处理的事情。
1/referenceCount
,并且通过SIGNAL_PULSE_COUNT
缩放分数,OP 可以容忍一些小误差,直接使用power_of_2/x
太慢了。假设SIGNAL_PULSE_COUNT == 0
不是问题。请给这篇文章一些时间。 - chux - Reinstate Monica