CSAPP数据实验Datalab

满分参考

bitAnd

获取x、y的位与结果

由德摩根律可直接得到答案

/* 
 * bitAnd - x&y using only ~ and | 
 *   Example: bitAnd(6, 5) = 4
 *   Legal ops: ~ |
 *   Max ops: 8
 *   Rating: 1
 */
int bitAnd(int x, int y) {
  return ~((~x)|(~y));//~(AB) = ~A + ~B
}

getByte

获取x的指定字节

可以先将所求字节利用右移移到最低位,然后用掩码提取最低位字节

/* 
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) {
  return (x>>(n<<3))&0xff;
}

logicalShift

实现逻辑右移

由于>>为算术右移,采用符号位补位,因此只需将补位的部分全部变为0即可
于是将x的算术右移结果与一个正的全1掩码的算术右移结果相与即可

/* 
 * logicalShift - shift x to the right by n, using a logical shift
 *   Can assume that 0 <= n <= 31
 *   Examples: logicalShift(0x87654321,4) = 0x08765432
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3 
 */
int logicalShift(int x, int n) {
  int temp;
  x = (x>>n);
  temp = ~(1<<31);//0x7fffffff 
  temp = ((temp>>n)<<1)|1;
  return x&temp;
}

bitCount

统计x中所有位上1的个数

分治,依次使用掩码计算每一位,每两位,每四位……每32位中的1个数,采用类似归并排序的分割方式。

具体思想为

  • 先用0…0 1…1相与统计右半的1的个数
  • 然后将原数右移一半,相与统计刚刚对应0…0位上的数中1的个数。
  • 然后就得到0…0 1…1 0…0 1…1中左半与右半中的1的个数
  • 再采用同样的方法将左右的1的个数相加,最后即可得到结果
/*
 * bitCount - returns count of number of 1's in word
 *   Examples: bitCount(5) = 2, bitCount(7) = 3
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 40
 *   Rating: 4
 */
int bitCount(int x) {
    int mask_1,mask_2,mask_4,mask_8,mask_16;
	mask_1=0x55|(0x55<<8);
	mask_1=mask_1|(mask_1<<16);//get 0x55555555
	mask_2=0x33|(0x33<<8);
	mask_2=mask_2|(mask_2<<16);//get 0x33333333
	mask_4=0x0f|(0x0f<<8);
	mask_4=mask_4|(mask_4<<16);//get 0x0f0f0f0f
	mask_8=0xff|(0xff<<16);//get 0x00ff00ff
	mask_16=0xff|(0xff<<8);//get 0x0000ffff
	x=(x&mask_1)+((x>>1)&mask_1);
	x=(x&mask_2)+((x>>2)&mask_2);
	x=(x+(x>>4))&mask_4;//x=(x&mask_4)+((x>>4)&mask_4);
	x=(x+(x>>8))&mask_8;//x=(x&mask_8)+((x>>8)&mask_8);
	x=(x+(x>>16))&mask_16;//x=(x&mask_16)+((x>>16)&mask_16);
	return x;
}

bang

实现!操作

!0 = 1,其他都等于0
只有0和0x80000000的补码与自己相或后是自己本身,而其中只有0最高位为0
于是只要判断一个数与其补码相同且最高位为0时结果为1,其余都为0

/* 
 * bang - Compute !x without using !
 *   Examples: bang(3) = 0, bang(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int bang(int x) {
  int temp = ~x+1;
  return (~((temp|x)>>31))&1;//the highet bit 
}

tmin

求最小的二进制补码

最小的二进制补码为0x80000000

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  return 0x80<<24;
}

fitBits

判断x是否能被n位的补码表示

即判断x的有效位数

  • 先用temp求出原数的位数与n位之间的位数差
  • 然后左移消去高位的数
  • 算术右移回来,倘若可以表示,则x此时应与原来相等
  • 比较原数与此时的x即可,若相等则为1
/* 
 * fitsBits - return 1 if x can be represented as an 
 *  n-bit, two's complement integer.
 *   1 <= n <= 32
 *   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int fitsBits(int x, int n) {
  int temp = 32 + (~n) +1;//unused bits
  int x1 = ((x<<temp)>>temp);
  return !(x^x1);//if equal
}

divpwe2

计算x除以2的n次的结果

将原数右移,右移n位即除以2的n次
由于负数的舍入与正数不同,判断是负数时在第n位加上1从而实现手动舍入

/* 
 * divpwr2 - Compute x/(2^n), for 0 <= n <= 30
 *  Round toward zero
 *   Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int divpwr2(int x, int n) {
	int sign = x>>31;//sign
	int temp = sign&((1<<n)+(~0));//if negetive
    return (x+temp)>>n;
}

negate

求负数

取补码加一即可

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return (~x+1);
}

isPositive

判断是否为正数

当x=0或符号位为1时返回0

/* 
 * isPositive - return 1 if x > 0, return 0 otherwise 
 *   Example: isPositive(-1) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 3
 */
int isPositive(int x) {
  return !((!x)|(x>>31));//if x=0 then !x=1
}

isLessOrEqual

判断x是否小于等于y

相减后得到符号,当xy同号且x<=y时或y为负x为正时x<=y

/* 
 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLessOrEqual(int x, int y) {
  int sign = ((y + (~x) +1)>>31)&1;//the sign of y-x
  int fx = (x>>31)&1;
  int fy = (y>>31)&1;
  return ((~(fy^fx)&(!sign)) |//the same signs and y-x>=0
         ((fy^fx)&fx) );//x<0, y>0 overflow
}

ilog2

求log2 x

即寻找最高位的1的位置,同样采用分治法依次判断左半部分位上有无1

/*
 * ilog2 - return floor(log base 2 of x), where x > 0
 *   Example: ilog2(16) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 90
 *   Rating: 4
 */
int ilog2(int x) {
  //find the highest 1
  int t16, t8, t4, t2, t1, temp;
  temp = !!(x>>16);//if 1 exists in the higher 16 bits, temp = 1
  t16 =  temp<<4;//2^4
  x=x>>t16;
  
  temp = !!(x>>8);//if 1 exists in the higher 8 bits, temp = 1
  t8 =  temp<<3;//2^3
  x=x>>t8;
  
  temp = !!(x>>4);//if 1 exists in the higher 4 bits, temp = 1
  t4 =  temp<<2;//2^2
  x=x>>t4;
  
  temp = !!(x>>2);//if 1 exists in the higher 2 bits, temp = 1
  t2 =  temp<<1;//2^1
  x=x>>t2;
  
  temp = !!(x>>1);//if 1 exists in the higher 16 bits, temp = 1
  t1 =  temp;//2^0
  
  return t16+t8+t4+t2+t1;
}

float_neg

浮点数取反

当uf不为NaN时使用异或取反符号位

/* 
 * float_neg - Return bit-level equivalent of expression -f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned float_neg(unsigned uf) {
 int exp = (uf>>23)&0xff;
 int frac = uf&((1<<23)-1);
 if((exp^0xff)||(!frac)){//exp!=nan or frac!=0
 	uf = (1<<31)^uf;
 }
 return uf;
}

float_i2f

将int转换为float的字节表示

根据转换公式和左移小数点的操作即可

  • 偏移量:左移小数点的位数加上bias
  • 小数部分:小数点移完后的小数部分
  • 符号位:不变
/* 
 * float_i2f - Return bit-level equivalent of expression (float) x
 *   Result is returned as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point values.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_i2f(int x) {
  int sign,temp,aftershift,shift_times, flag;
  sign = x&(1<<31);
  if(sign){//abs x
  	x = -x;
  }
  if(!(x)){//x=0
	return 0;
  }
  aftershift = x;
  shift_times = 0;
  while(1){
  	temp = aftershift;
  	aftershift = aftershift<<1;
  	shift_times ++;
  	if(temp&0x80000000){//1 in the highest bit
  	  break;
	}
  } 
  //carry bit
  if(((aftershift&0x01ff)>0x0100) ||
  		((aftershift&0x03ff))==0x0300){
  	flag = 1;
  } 
  else{
  	flag = 0;
  }
  //sign + exp + frac + flag
  //E=32-shift_times
  return sign+(((159-shift_times)<<23)&0x7f800000)+((aftershift>>9)&0x7fffff)+flag;
}

float_twice

求浮点数乘2的结果的浮点数表示

规格化数exp加一,非规格化数左移一位,NaN不变

/* 
 * float_twice - Return bit-level equivalent of expression 2*f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representation of
 *   single-precision floating point values.
 *   When argument is NaN, return argument
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_twice(unsigned uf) {
  if((uf&0x7f800000) == 0){//unnormalized
  	return ((uf&0x7fffff)<<1)|(uf&0x80000000);
  }
  if((uf&0x7f800000) != 0x7f800000){
  	return uf+0x800000;
  }
  return uf;//NaN
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值