csapp-homework-2.75(2)
2.75题目描述
Suppose we want to compute the complete 2w-bit representation of x . y, where both x and y are unsigned, on a machine for which data type unsigned is w bits.
The low-order w bits of the product can be computed with the expression x*y, so we only require a procedure with prototypeunsigned unsigned_high_prod(unsigned x, unsigned y);that computes the high-order w bits of
x*yfor unsigned variables.
We have access to a library function with prototypeint signed_high_prod(int x, int y);that computes the high-order w bits of x . y for the case where x and y are in two’scomplement form. Write code calling this procedure to implement the function for unsigned arguments.
Justify the correctness of your solution.Hint: Look at the relationship between the signed product x . y and the unsigned product x. y
in the derivation of Equation 2.18.
等式2.18为:

这个问题抽象为程序语言的话,就是:
乘法得出的2w位数据被保存在2w位变量
unsigned_prd中,分别再用w位的变量
unsigned_high_bits和unsigned_low_bits,分别去保存变量unsigned_prd的高w位和低w位。
而协助完成这个保留无符号数乘法结果高w位的方法,是对应有符号数保留高w位的方法signed_high_prod。
我们需要找到有符号数高w位和无符号数高w位之间的关系,因为我们已经知道无符号数乘法和有符号数乘法最终结果的二进制表示是一致的,而最终结果就是乘法的结果对2^w求模运算得来的。
假设不截断无符号整数的乘法结果(2w位):unsigned_prd = ux * uy
那么截断为低w位的结果为:unsigned_low_bits = unsigned_prd mod 2^w.
这样乘法结果的高w位数据就可以得出:unsigned_high_bits =  (unsigned_prd - unsigned_low_bits ) mod 2^w
这里需要强调下,unsigned_prd是2w位的无符号变量,而保存其高、低w位的无符号变量unsigned_high_bits和unsigned_low_bits均为w位数据。
同理也可以得到有符号数的高低w位数据,其实公式都相同,只是把unsigned改为signed。
上述分析结束,就可以利用公式去推导下“如何利用有符号数乘法的高w位去表示无符号数的高w位”,我这里想用markdown自带的公式写的,寻思这样更清晰一些,但是上面等式2.18敲完了我就打了退堂鼓--因为语法太麻烦了!
这样我就在这贴一下自己手写的推导公式:
这样再去理解代码就方便很多了。贴一下2.75答案
/*
 * unsigned-high-prod.c
 */
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
int signed_high_prod(int x, int y) {
  int64_t mul = (int64_t) x * y;
  return mul >> 32;
}
unsigned unsigned_high_prod(unsigned x, unsigned y) {
  /* TODO calculations */
  int sig_x = x >> 31;
  int sig_y = y >> 31;
  int signed_prod = signed_high_prod(x, y);
  return signed_prod + x * sig_y + y * sig_x;
}
/* a theorically correct version to test unsigned_high_prod func */
unsigned another_unsigned_high_prod(unsigned x, unsigned y) {
  uint64_t mul = (uint64_t) x * y;
  return mul >> 32;
}
int main(int argc, char* argv[]) {
  unsigned x = 0x12345678;
  unsigned y = 0xFFFFFFFF;
  assert(another_unsigned_high_prod(x, y) == unsigned_high_prod(x, y));
  return 0;
}
这里只是讲了关于有符号和无符号数乘法的关系,对于整体的描述可以看之前的帖子csapp-homework-2.75
欢迎讨论csapp的相关问题~😉
                    
                
                
            
        
浙公网安备 33010602011771号