【问题标题】:why Q.15 multiplication isn't working为什么 Q.15 乘法不起作用
【发布时间】:2014-03-21 13:22:00
【问题描述】:

参考Notation for fixed point representation 我已经尝试关注,但我完全糊涂了。

int q = 1<<15;
printf("(sys3.b0 * q) = %hx \n",((0.2929 * q)));

输出是

((0.2929 * q)) = cc60

我希望看到 257d,因为来自计算器,0.2929 * 32768 in hex = 257d

使用这种 Q.15 格式有什么问题,还是因为打印不正确


编辑

伙计们,其实我从来没有想过。

我的实际代码尝试打印两个值。我认为第二值印刷是问题所在。在@Soren 的cmets 之后,我复制了他的代码并且正在工作。然后我从 printf 中删除了第一个值,我的代码也有效。所以我重新发布了 printf 声明

printf("(sys3.b0 * q) = %X \t((0.2929 * q)) = %X\n",(sys3.b0 * q),(unsigned)((0.2929 * q)));
printf("(sys3.b0 * q) = %X \n",((unsigned)(0.2929 * q)));

第二行是 Seron 建议的。

The value of sys3.b0 = 0.0000000001295

现在输出是

(sys3.b0 * q) = 4DB173CF        ((0.2929 * q)) = 3ED1CC60
(sys3.b0 * q) = 257D

【问题讨论】:

    标签: c printf signal-processing fixed-point


    【解决方案1】:

    你所拥有的是undefined behavior的结果:

    0.2929 * q
    

    是双精度数,但您告诉 printf 它是无符号短。如果您将结果转换为 unsigned short,您将得到您期望的结果 (see it live):

    printf("(sys3.b0 * q) = %hx \n",(unsigned short)(0.2929 * q));
                                    ^^^^^^^^^^^^^^^^
    

    打开或打开警告应该表明这是一个问题,gccclang 都给出了类似的错误:

    警告:格式“%hx”需要“int”类型的参数,但参数 2 的类型为“double”[-Wformat=]

    虽然 Visual Studio 显然没有。

    【讨论】:

    • 我在 MS VC++ 环境中,并且所有警告都出现了。类型转换仍然产生相同的输出
    • @nmxprime 我添加了一个实时示例,此代码在 Visual Studio 中正常工作。
    • @nmxprime 仍然未定义行为将(sys3.b0 * q) 更改为(unsigned)(sys3.b0 * q)
    • 谢谢!很好,但是对这种不寻常的行为有任何暗示吗?可能是Windows的做法?现在我没有 linux pc 用 gcc 测试它
    • @nmxprime 您可以通过众多可用的online compilers 之一使用gccclang。未定义的行为意味着当您指定 %X 但传入 double 时,该行为是不可预测的>
    【解决方案2】:

    格式字符串需要与您实际提供的类型不同的类型。我的编译器说:

    foo.c:5:33:警告:格式指定类型“无符号短”,但参数的类型为“双”[-Wformat]

    因此,您需要一个转换来将 0.2929 * qdouble 转换为 unsigned int。像这样:

    int main() {
        int q = 1<<15;
        printf("(sys3.b0 * q) = %X \n",((unsigned)(0.2929 * q)));
    }
    

    编辑:当您向printf 提供错误类型的参数时,它只会读取与它所获得的类型一样多的字节认为。在你的情况下:

    printf("(sys3.b0 * q) = %X \t((0.2929 * q)) = %X\n",
           (sys3.b0 * q),
           (unsigned)((0.2929 * q)))
    

    格式字符串表示期望两个unsigned int,即两倍 4 字节*。但是你给了它一个double 和一个unsigned int,它们分别是 8 和 4 字节*。 printf 只为每个 %X 读取 4 个字节,因此它有效地读取了 sys3.b0 * q 的 8 个结果,认为这 8 个字节是两个整数,然后将其打印出来。

    【讨论】:

    • (unsigned)((0.2929 * q)) 仍然给出相同的结果。我正在使用 MS VC++
    • %hx 更改为%x 得到3ed1cc60
    • 很奇怪。也许尝试复制我上面的程序,以确保没有错字?
    • 你的程序有效!!经过测试,我发现了更奇怪的事情!让我相应地编辑问题
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 2012-12-13
    • 2010-11-19
    • 2021-01-29
    • 2023-03-03
    相关资源
    最近更新 更多