得到32位高位乘以两个无符号整数(HW)

时间:2016-05-03 13:24:04

标签: c bits

我正在阅读CSAPP并尝试完成作业问题。假设w = 32,2.75是关于从两个32位无符号整数乘以高32位。给定函数int signed_high_prod(int x, int y),它计算x的高阶32位。 y表示x和y为二进制补码形式的情况。 int signed_high_prod(int x, int y)应该用于实施unsigned int unsigned_high_prod(unsigned x, unsigned y)

通过谷歌搜索我发现x'.y' = x.y + x.y_31.2^32 + y.x_31.2^32 + x_31.y_31.2^64,其中x'和y'分别是x和y的无符号形式。

我仍然无法理解答案。

unsigned unsigned_high_prod(unsigned x, unsigned y){
    unsigned p = (unsigned) signed_high_prod((int) x, (int) y)
    if((int) x < 0){
        p += y;
    }
    if((int) y < 0){
        p += x;
    }
    return p;
}

为什么最终用语对结果没有影响?为何x < 0 x_31 = 1,加上y?与y相同。

3 个答案:

答案 0 :(得分:2)

要执行位级乘法,我们必须首先扩展位,然后进行一系列的移位和加法。例如,假设w = 3,请x = [011]y = [101]。 (即x = 3y = -3 (signed) or 5 (unsigned)

要执行未签名的产品,我们首先按如下方式进行零扩展:(忽略位6及以上)

     000 011
   * 000 101
    --------
     000 011
   + 001 100
    --------
     001 111
    ========

因此,无符号高位为[001]

要执行已签名的产品,我们首先按以下方式进行签名扩展:

     000 011
   * 111 101
    --------
     000 011
   + 001 100
   + 011 000  **
   + 110 000  **
   + 100 000  **
    --------
     110 111
    ========

因此,带符号的高位是[110]

注意,有符号和无符号高位之间的差异(如上面**所示)是我们在签名的情况下添加了[111] * [011]。因此,我们必须减去此数量以获得无符号高位。

The unsigned high order bits = [110] - [111] * [011]
                             = [110] - [101]
                             = [110] + [011] ??
                             = [001] (as above) 

由于[111] = -1,更正金额- [111] * [011]相当于- (-1 * x) = x

因此,当y为负数时(如本例所示),我们必须通过添加x来更正结果。同样地,当x为否定时,我们必须通过添加y来更正结果。

?? -[101] = ~[101] + 1 = [010] + [001] = [011]

答案 1 :(得分:1)

要将带符号,2的补码,32位整数转换为无符号的32位整数,如果它是负数,我们将其值加2³。

signed_high_prod执行带符号的乘法并返回乘积的第63到32位。我们希望unsigned_high_prod对无符号乘法执行相同操作并使用signed_high_prod,然后补偿无符号和有符号乘法之间的差异。

Let N(i) = { 1, i < 0
           { 0, i >= 0

Let U(i) = i + N(i)·2³² { −2³¹ <= i < 2³¹ }

然后:

U(x)·U(y) = (x + N(x)·2³²)·(y + N(y)·2³²)
          = x·y + x·N(y)·2³² + N(x)·2³²·y + N(x)·2³²·N(y)·2³²
          = x·y + x·N(y)·2³² + y·N(x)·2³² + N(x)·N(y)·2⁶⁴

⌊U(x)·U(y)/2³²⌋ = ⌊x·y/2³²⌋ + x·N(y) + y·N(x) + N(x)·N(y)·2³²

由于对无符号32位整数的算术将以2 3 2为模进行,我们有:

⌊U(x)·U(y)/2³²⌋ mod 2³²  = (⌊x·y/2³²⌋ + x·N(y) + y·N(x) + N(x)·N(y)·2³²) mod 2³²
                         = (⌊x·y/2³²⌋ + x·N(y) + y·N(x)) mod 2³²

我认为会考虑您的unsigned_high_prod功能执行的计算。

答案 2 :(得分:1)

  • x'.y'= x.y + x.y_31.2 ^ 32 + y.x_31.2 ^ 32 + x_31.y_31.2 ^ 64

这是您应该了解的前提条件

  1. x'和y'是无符号的,而x,y是有符号的

  2. 通过使用“ mod 2 ^ 32”获得x * y的低阶32位

  3. 通过使用“ / 2 ^ 32”来获得x * y的高阶32位

开始吧

要获取x'* y'的高32位,我们使用“ / 2 ^ 32”

x'.y' /  2^32=unsigned_high_prod(unsigned x,unsigned y)
=(x.y + x.y_31.2^32 + y.x_31.2^32 + x_31.y_31.2^64)/2^32
=x.y/2^32 + x.y_31 + y.x_31 + x_31.y_31.2^32
=signed_high_prod(int x, int y) + x.y_31 + y.x_31 + x_31.y_31.2^32

但是我们得到的不限于32位,显然结果y.x_31 + x_31.y_31.2 ^ 32溢出了,我们应该得到的只是32位数字。因此,我们使用mod 2 ^ 32来获得正确的答案。

(signed_high_prod(int x,int y)+ x.y_31 + y.x_31 + x_31.y_31.2 ^ 32)mod 2 ^ 32 = signed_high_prod(int x,int y)+ x.y_31 + y.x_31

其结尾为:

unsigned_high_prod(unsigned x,unsigned y)=     Signed_high_prod(int x,int y)+ x.y_31 + y.x_31

因此很明显,代码是正确的。

因为如果int x <0,则意味着x_31 == 1,因此必须加y。

否则x_31 == 0,因为y.x_31 == 0,您无需做任何事情

与y相同