我对如何处理一些定点计算有疑问。我不知道如何解决。我知道浮点运算很容易,但是我想弄清楚固定点的运算方法。
我有一个定点系统,在该系统上我对信号(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
有任何想法吗?
最佳答案
“如果我尝试用Q格式表示值2.8928,可以说Q12。该值更改为11849。现在10 ^ 11849导致溢出。”
混合数学很难,看来应该避免使用。您想要的是pow(Q12(10.0), Q12(2.8928))
或可能是优化的pow10(Q12(2.8928))
。首先,请参见my previous answer。后者可以通过硬编码的功率表进行优化。 pow10(2.8928)
当然是pow10(2) * pow10(.5) * pow10(.25) * pow10(.125) * ...
-2.8928
的二进制表示形式中的每个1对应于一个表条目。您可能需要计算Q19.44中的中间结果,并在返回时丢弃最低的32位。
编辑:精度
存储pow10(2^-n)
的所有值直到n = 12都有一个小问题,即结果接近1,即1.000562312
。如果将其存储为Q12,则舍入精度会下降。取而代之的是,将pow10(2^-12)
的值存储为Q24,将pow10(2^-121)
的值存储为Q23,等等。现在,从Q12 pow10(Q12 exp)
的LSB而不是MSB开始评估exp
。在上移至pow10(0.5)
时,您需要重复移动中间结果,但有一半的时间可以将其与Q12乘法固有的>>12
合并。
关于c++ - 定点电源功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58389261/