签名&无符号整数乘法

时间:2013-06-06 15:51:21

标签: c math types multiplication fixed-point

在定点数学中,我使用了大量的16位信号,并使用32位中间结果进行乘法运算。例如:

int16_t a = 16384; //-1.0q14  or 1.0*2^14
int16_t b = -24576; // -1.4q14  or 1.4*2^14
int16_t c; // result will be q14

c = (int16_t)(((int32_t)a * (int32_t)b)>>14);

让我们说a是q14数,然后c与b具有相同的比例。

这很好,适用于无符号和带符号算术。

问题是:如果我要混合类型会发生什么?例如,如果我知道乘数“a”总是在0.0到1.0的范围内,那么很容易使它成为无符号整数q15以获得额外的精度(并将移位计数更改为15)。但是,我从未理解如果你试​​图在C中乘以有符号和无符号数并避免它会发生什么。在ASM中,我不记得有任何多重指令可以在任何架构上使用混合类型,所以即使C做正确的事我也不确定它会生成有效的代码。

我是否应该继续不在定点代码中混合签名的无符号类型?或者这可以很好地工作吗?

2 个答案:

答案 0 :(得分:5)

This post谈论有符号和无符号整数相乘时会发生什么。简短的回答是,只要它们具有相同的等级(大小),签名就会隐式强制转换为无符号。

只要你理解了类型转换规则(你正在编程的任何语言),或者使用明确的类型转换,你也理解从签名到无符号的类型转换的含义(负数会产生可能看起来像胡言乱语的时候对于有符号值和无符号类型,应该没有问题。

答案 1 :(得分:0)

我有类似的问题。它导致了x64版本的访问冲突崩溃。代码遍历图像扫描线的缓冲区。获取下一个扫描线指针的方式如下:

unsigned char* pImg = ...
int stride = -3324;
unsigned int iRow = 1; // 2, 3, 4, ...
unsigned char* pNextLine = pImg + stride * iRow

负跨度表示从底部扫描到顶部扫描线。产品stride * iRowsigned * unsigned被类型转换为unsigned __int64,其值为4294963972,这将pNextLine推出程序的内存。

x32程序版本也是如此,但是没有崩溃。也许是因为x32 pNextLine指针只是回绕(但停留在程序的内存中)。