CSAPP datalab 题解+思路

/* 
 * bang - Compute !x without using !
 *   Examples: bang(3) = 0, bang(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int bang(int x) {
	int tmp = x | (~x+1);
	tmp = (tmp >> 31) + 1;
  return tmp;
}
/* 
 * logicalNeg - implement the ! operator, using all of 
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int logicalNeg(int x) {
	int tmp = x | (~x+1);
	tmp = (tmp >> 31) + 1;
  return tmp;
}

bang or logicalNeg

思路:只有0的补码位或本身首位为0

/*
 * 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,s;
	mask = 0x11 | (0x11 << 8);
	mask = mask | (mask << 16);
	s = x&mask;
	s = s + ((x>>1)&mask);
	s = s + ((x>>2)&mask);
	s = s + ((x>>3)&mask);
	s = s + (s>>16);
	mask = 0xF | (0xF << 8);
	s = (s&mask) + ((s>>4)&mask);
  return (s + (s>>8)) & 0x3F;
}

bitCount

思路:

先构建0x11111111,再分别将x右移三次获得每个byte里1的个数(不大于4)

将前半段计数与后半段相加,此时后四个byte里存储两个byte中1的个数(不大于8)

以此类推,再进行两次合并即可得到所有的bit数

/* 
 * copyLSB - set all bits of result to least significant bit of x
 *   Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int copyLSB(int x) {
	x = x << 31;
	x = x >> 31;
  return x;
}

countingLSB

思路:简单,不解释

/* 
 * evenBits - return word with all even-numbered bits set to 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 2
 */
int evenBits(void) {
	int n = 0x55;
	n = (n<<8) | n;
	n = (n<<16) | n;
  return n;
}

evenBits

思路:构建一个mask,复制两次即可(参考bitCount)

/* 
 * 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 t = x;
	int minus = 32 + (~n+1);
	x = x<<minus;
	x = x>>minus;
  return !(t^x);
}

fitsBits

思路:若可以用n-bits表示那么左移32-n位再右移32-n后和原来相同

/* 
 * 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) {
	int m = n<<3;
	int mask = 0xff << m;
	x = (mask & x) >> m;
	x = x&0xff;
  return x;
}

getByte

简单不解释

/* 
 * isGreater - if x > y  then return 1, else return 0 
 *   Example: isGreater(4,5) = 0, isGreater(5,4) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isGreater(int x, int y) {
	int x1 = (x >> 31) & 1;
	int y1 = (y >> 31) & 1;
	int xy = !!(x^y);
	int minus = !((x + (~y+1)) >> 31);
	int ans = ((x1^y1)&y1) | (xy & minus & (!(x1^y1)));
  return ans;
}

isGreater

思路:

考虑是否一正一负,若x正y负则返回1;(x1^y1)&y1

考虑是否相等,相等则返回0;!!(x^y)

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

 isNonNegative

/* 
 * isNotEqual - return 0 if x == y, and 1 otherwise 
 *   Examples: isNotEqual(5,5) = 0, isNotEqual(4,5) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int isNotEqual(int x, int y) {
  return !!(x^y);
}

isNotEqual

/* 
 * leastBitPos - return a mask that marks the position of the
 *               least significant 1 bit. If x == 0, return 0
 *   Example: leastBitPos(96) = 0x20
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 4 
 */
int leastBitPos(int x) {
	int m = ~x + 1;
	int n = m & x;
  return n;
}

leastBitPos

思路:考虑leastBitPos之前都是0,取反加一后leastBitPos位为1,亦或原数字后只有该位为1,则为答案

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

logicalShift

思路:用带0的mask覆盖即可

/*
 * satAdd - adds two numbers but when positive overflow occurs, returns
 *          maximum possible value, and when negative overflow occurs,
 *          it returns minimum positive value.
 *   Examples: satAdd(0x40000000,0x40000000) = 0x7fffffff
 *             satAdd(0x80000000,0xffffffff) = 0x80000000
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 30
 *   Rating: 4
 */
int satAdd(int x, int y) {
	int add,over,pover,nover,ans;
	add = x+y;
	over = (add^x)&(add^y);
	pover = ((over&~x)>>31)&1;
	nover = ((over&x)>>31)&1;
	ans = ((~(1<<31))&(~pover+1))+((1<<31)&(~nover+1))+((~(!(pover|nover))+1)&add);
  return ans;
}

satAdd

思路:

溢出只有两种情况,xy都正 x+y为负,xy都负 x+y为正,over变量可以监控是否溢出

结合over和x的正负可以判断是positive_over 还是 negative_over

答案讨论三种情况:pover则返回Tmax,nover则返回Tmin,都不溢出则返回计算值

/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */
int howManyBits(int x) {
	int mask,cal,tmp,dig = 16,minus = ~0,add;
	tmp = x;
	x = ((x>>31) ^ x) + !!(x>>31);
	mask = ~((1<<dig)+minus);
	cal = !!(x&mask);
	cal = ((cal << 1) + minus) << 3;
	dig = dig+cal;
	mask = ~((1<<dig)+minus);
	cal = !!(x&mask);
	cal = ((cal << 1) + minus) << 2;
	dig = dig+cal;
	mask = ~((1<<dig)+ minus);
	cal = !!(x&mask);
	cal = ((cal << 1) + minus) << 1;
	dig = dig+cal;
	mask = ~((1<<dig)+minus);
	cal = !!(x&mask);
	cal = ((cal << 1) + minus);
	dig = dig + cal;
	mask = ~((1<<dig) + minus);
	cal = !!(x&mask);
	dig = dig + cal;
	mask = ((1<<(dig+minus))+minus);
	add = !!(x&mask);
  return (add&(tmp>>31)) + dig + !(tmp>>31) + (~(!tmp)) + 1;
}

howManyBits

思路:

先统一变为正数计算

构建mask = 0xffff0000,若mask&x为0则继续考虑0xffffff00,若为1则考虑0xff000000

以此类推,直到确定位数,在此基础上+1(符号位)

接下来考虑是否为负数且最高位的后一位是否为1,若是,则位数+1

/* 
 * 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 x1 = (x >> 31) & 1;
	int y1 = (y >> 31) & 1;
	int xy = !!(x^y);
	int minus = !((x + (~y+1)) >> 31);
	int ans = ((x1^y1)&y1) | (xy & minus & (!(x1^y1)));
  return !ans;
}

isLessOrEqual

思路:isGreater结果取反(见上)

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.-.891

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值