定点幂函数

Fixed point power function

我对如何处理一些定点计算有疑问。我不知道如何解决它。我知道在浮点数中很容易,但我想弄清楚如何在定点数中做到这一点。

我有一个定点系统,我在其中对信号 (vSignal) 执行以下等式:

Signal_amplified = vSignal * 10^Exp

vSignal 的最大幅度约为 4e+05,

系统允许表示 2.1475e+09(32 位)信号。所以 Signal_amplified.

有一些余量

为简单起见,只假设 Exp 可以从 0 到 10。

假设第一个值为 2.8928。该值在以浮点计算时效果很好,因为表达式 10^2.8928 的结果为 781。当使用四舍五入的浮点值 781 时,我得到的信号幅度为 3.0085e+08,完全在信号范围内。

如果我尝试用 Q 格式表示值 2.8928,假设是 Q12。该值更改为 11849。现在 10^11849 导致溢出。

应该如何处理这些大数字??我可以使用另一种格式,如 Q4,但即便如此,数字也会变得非常大,我的格式也会变得很差。我非常希望能够以 .001 的精度进行计算,但我只能看到应该如何完成。

最小工作示例:

int vSignal = 400000

// Floatingpoint -> Goes well
double dExp = 2.89285
double dSignal_amplified = vSignal * std::pow(10,dExp)

// Fixedpoint -> Overflow
int iExp = 11848 // Q12 format
int iSignal_amplified = vSignal * std::pow(10,iExp)
iSignal_amplified =  iSignal_amplified>>12

有什么想法吗?

这是一个提案。只是一个粗略的想法,有待调整和完善。

假设您需要 0.01 的精度(当然您可以选择您需要的精度),您可以将指数表示为: Exp = N + M*10^-1 + P*10^-2 其中 N、M 和 P 是整数,M 和P 介于 0 和 9 之间。

然后您预先计算并四舍五入 10^(M*10^-1) * 10010^(P*10^-2) * 100 的所有值。它们都在 1 到 1000 之间。将它们存储在查找 table 中以避免在运行时计算浮点运算。我们将这些查找 table 称为 A[M] 和 B[P]。

然后你可以计算10^Exp =( 10^N * A[M] * B[P] ) / 10000

乘法应该不会溢出,因为 A[M] * B[P] 介于 1 和 1,000,000 之间,并且根据您所说的 A 小于 10。

我用几个值做了一个快速测试,它似乎给出了 acceptable 精度。

"If i try to represent the value 2.8928 with a Q format of, lets say Q12. The value changes to 11849. Now 10^11849 results in overflow.".

混合类型的数学很难,看起来你应该避免它。您想要的是 pow(Q12(10.0), Q12(2.8928)) 或者可能是优化的 pow10(Q12(2.8928))。首先,请参阅 my previous answer。后者可以通过硬编码 table 的权力进行优化。 pow10(2.8928) 当然是 pow10(2) * pow10(.5) * pow10(.25) * pow10(.125) * ... - 2.8928 的二进制表示中的每个 1 对应一个 table 条目。您可能希望在 Q19.44 中计算中间结果,并在 return..

时删除最低的 32 位

编辑:精度

pow10(2^-n)的所有值存储到n=12有一个小问题,即结果接近1,即1.000562312。如果将其存储为 Q12,则会失去四舍五入的精度。相反,将 pow10(2^-12) 的值存储为 Q24,将 pow10(2^-121) 的值存储为 Q23 等可能是明智的。现在从 exp 的 LSB 开始评估 Q12 pow10(Q12 exp) ,而不是 MSB。当您移动到 ​​pow10(0.5) 时,您需要反复移动中间结果,但有一半时间您可以将其与 Q12 乘法固有的 >>12 合并。