我对如何处理一些定点计算有疑问。我不知道如何解决。我知道浮点运算很容易,但是我想弄清楚固定点的运算方法。
我有一个定点系统,我在该系统上对信号(vSignal)执行以下方程式:
Gson gson = new GsonBuilder().registerTypeAdapter(Article.class, new CustomDeserializer()).create();
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的精度进行计算,但是我只能看到应该怎么做。
最小工作示例:
@Expose
有什么想法吗?
答案 0 :(得分:1)
这是个提案。这只是一个粗略的想法,需要进行调整和完善。
假设您需要一个0.01
的精度(您可以选择所需的精度),您可以将指数表示为:Exp = N + M*10^-1 + P*10^-2
其中N,M和P是整数,而M和P是在0到9之间。
然后,您预先计算并舍入10^(M*10^-1) * 100
和10^(P*10^-2) * 100
的所有值。它们都在1到1000之间。将它们存储在查找表中,以避免在运行时计算浮点运算。我们将这些查询表称为A [M]和B [P]。
然后您可以计算10^Exp =( 10^N * A[M] * B[P] ) / 10000
乘积不会溢出,因为A[M] * B[P]
在1到1,000,000之间,并且根据您的说法A小于10。
我用几个值进行了快速测试,似乎给出了可接受的精度。
答案 1 :(得分:1)
“如果我尝试用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开始计算exp
,而不是MSB。在向上移动到pow10(0.5)
时,您需要重复移动中间结果,但是有一半的时间可以将其与Q12乘法固有的>>12
合并。