【问题标题】:Fixed-point scaling and accuracy in multiplication定点缩放和乘法精度
【发布时间】:2013-09-27 17:24:57
【问题描述】:

我需要对系数为A 的定点变量x(无符号16 位整数[U16] 类型,二进制点6 [BP6])执行乘法运算,我知道它总是介于 0 和 1 之间。代码是用 C 编写的,用于 32 位嵌入式平台。

我知道,如果我也让这个系数成为 U16 BP6,那么我最终会从乘法中得到一个 U32 BP12。我想将此结果重新缩放回 U16 BP6,所以我只去掉前 10 位和后 6 位。

但是,由于系数的精度受小数位数的限制,而且我不一定需要整 10 位整数,我想我可以将系数变量 A U16 BP15 设为产生更精确的结果。

我已经制定了以下示例(请耐心等待):

假设x = 172.0(十进制),我想使用系数A = 0.82(十进制)。理想的十进制结果是 172.0 * 0.82 = 141.04。

二进制,x = 0010101100.000000

如果我对 A 使用 BP6,则二进制表示将是

    A_1 = 0000000000.110100 = 0.8125 or
    A_2 = 0000000000.110101 = 0.828125

(取决于价值是基于地板还是天花板)。

在 x 和 A 的任一值之间执行二进制乘法会产生(省略前导零):

    A_1 * x = 10001011.110000000000 = 139.75 
    A_2 * x = 10001110.011100000000 = 142.4375

在这两种情况下,减少最后 6 位不会影响结果。

现在,如果我将 A 扩展为 BP15,那么

    A_3 = 0.110100011110110 = 0.82000732421875

结果乘法产生

    A_3 * x = 10001101.000010101001000000000 = 141.041259765625

当修剪额外的 15 个小数位时,结果是

    A_3 * x = 10001101.000010 = 141.03125

所以这里很清楚,通过扩展系数以获得更多小数位会产生更精确的结果(至少在我的示例中)。这是否普遍适用?这在实践中使用是好还是坏?我是否遗漏或误解了什么?

编辑:我应该在这里说“准确度”而不是“精确度”。我正在寻找一个更接近我的预期值的结果,而不是一个包含更多小数位的结果。

【问题讨论】:

    标签: c precision fixed-point


    【解决方案1】:

    在完成了类似的代码之后,我想说的是,您所做的事情通常适用于以下问题。

    1. 围绕二进制点移动时很容易出现意外溢出。建议进行严格的测试/分析和/或代码检测。 Notable failure: Ariane_5

    2. 您想要精确,因此我不同意“关闭...最后 6 个”。相反,我建议在处理时间允许的情况下四舍五入您的结果。使用被截断的 MSBit 来调整结果。

    【讨论】:

    • 感谢您的意见。在这种情况下,应该永远不会出现溢出问题,因为我将检查系数是否永远不会超过 1.0。此外,我将结果缩放回 6 个小数位,因为它将在以后的计算中与其他 BP6 变量一起使用。因此,结果可能不一定精确,但至少在计算中。即使去除了结果中的小数位,最后的计算也更接近我想要的结果。
    • 也感谢您编辑以包含该显着失败。很高兴知道。
    • C 为编写真正巧妙的解决方案提供了绝佳的机会。 SDK 中还包含足以吊死自己的绳索。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 2018-07-19
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    相关资源
    最近更新 更多