【Ayanokoji/ICS Labs】01 DataLab

这里是新手Ayanokoji暑假偷卷ICS Lab的踩坑日记。【Data Lab篇】

用的是cmu官网上的lab片段。

1.BitXor Puzzle

int bitXor(int x, int y) {
  return ~(~x & ~y) & ~(x & y); //De Morgen
}

使用De Morgen定律易得。

2.TMin Puzzle

int tmin(void) {
  return 1<<31;
}

简单。

3.isTmax Puzzle

int isTmax(int x) {
  return !((~x)^(x+1))&(!!(~x));//后面为了判断是否是-1 
}

因为当时刚开始学,所以迷迷糊糊的,这个其实绕了远路。!((~x)^(x+1))在x为Tmax或者-1时运算结果时0,再用后面半段排除掉-1的情况即可。

4.allOddBits Puzzle

int allOddBits(int x) {
  return !((~x>>1)&(0x55+((0x55)<<8)+((0x55)<<16)+((0x55)<<24)));
}

依然绕了远路,将x取反后右移一位,那么所有的偶数位应该是0,再与0x55555555取和,应该得到0,最后使用boolean not即可。

5.negate Puzzle

int negate(int x) {
  return (~x)+1;
}

简单。

6.isAsciiDigit Puzzle

int isAsciiDigit(int x) {
  int lower_bound = 0x30; // 0
  int upper_bound = 0x39; // 9

  int is_greater_or_equal_lower = !((x + (~lower_bound + 1)) >> 31);
  int is_less_or_equal_upper = !((upper_bound + (~x + 1)) >> 31);

  return is_greater_or_equal_lower & is_less_or_equal_upper;
}

思路比较直接,先把0和9表示出来,再作差观察符号位是0还是1即可。

7.conditional Puzzle

int conditional(int x, int y, int z) {
	int mask = ~(!!x)+1;
	return ((mask&y)|(~mask&z));
}

比较经典的做法。如果x为0,其掩码全0,否则其掩码全1。Boolean not 在这里发挥了显著的作用。

8.isLessOrEqual Puzzle

int isLessOrEqual(int x, int y) {
	int t = x+(~y+1);
	return !(t) | !!((t>>31)&1);
}

先作差,看是否为0,符号位是正还是负。

9.logicalNeg Puzzle

int logicalNeg(int x) {
  return ((((~x + 1) | x)>>31)+1);//只有0的取反前后首位都为0 
}

正如注释所说,只有+0与-0的首位都是0,否则符号位必有一正一负。

10.howManyBits Puzzle

int howManyBits(int x) {
	int temp = x ^ (x << 1);
	int bit_16,bit_8,bit_4,bit_2,bit_1;
	bit_16 = !!(temp >> 16) << 4;
	temp = temp >> bit_16;
	bit_8 = !!(temp >> 8) << 3;
	temp = temp >> bit_8;
	bit_4 = !!(temp >> 4) << 2;
	temp = temp >> bit_4;
	bit_2 = !!(temp >> 2) << 1;
	temp = temp >> bit_2;
	bit_1 = !!(temp >> 1);
	return 1 + bit_1 + bit_2 + bit_4 + bit_8 + bit_16;
}

暴力做法,分别以2^n为界限考虑即可。

11.floatScale2 Puzzle

unsigned floatScale2(unsigned uf) {
	unsigned sign = uf>>31;
	unsigned exp = (uf>>23) &0xff;
	unsigned frac = uf& 0x7FFFFF;
	if(exp == 0xFF){
		return uf;
	} //NaN
	if(exp == 0){
		return (sign<<31)|(frac<<1);
	} 
	else{
		exp++;
		if(exp == 0xFF){
			return (sign<<31)|0x7F800000;//Overflow
		}
		else{
			return (sign<<31)|(exp<<23)|frac;
		}
	}
}

代码逻辑已经比较清楚了,不用赘述。

12.floatFloat2Int Puzzle

int floatFloat2Int(unsigned uf) {
	unsigned sign = uf>>31; 
    unsigned exp = uf>>23 & 0xFF;
    int frac = (uf & 0x7fffff) | 0x800000;//恢复前导1 
    int e = exp - 127;
    if (e < 0) {
        return 0;
    }
    if (e > 31) {
        return 0x80000000;    // 无穷大或者nan 
    }
    if (e > 23) {
        frac <<= (e - 23);
    } else {
        frac >>= (23 - e);
    }
    if (!((sign) ^ (frac >> 31))) {
        return frac;
    }
    if (frac >> 31) {
        return 0x80000000;// 符号位变化,且当前符号为负,说明溢出
    }
    return ~frac + 1;
}

本人觉得整个lab最麻烦的一道题,狠狠拷问了关于IEEE浮点数规则的理解。先移动小数点,再判断移动后的数是否溢出。

13.floatPower2 Puzzle

unsigned floatPower2(int x)
{
	signed posinf = 0x7F800000;
	int exp = 127+x;//这实际上是小数全为0的float形式
	if(exp>=255){
		return posinf;
	} 
	if(exp<=0){
		return 0;
	} 
	else{
		return exp<<23;
	}
}

比较简单。这个puzzle是一个比较简单的浮点数形式,也即exp位非0,小数位全为0。我们只需要判断exp位是否可以表示,是否会溢出即可。

至此,Datalab的所有问题都解决完毕。放一个autograder的截图如下:

请忽略左边露出来的一点ide背景

那么我们下周Bomblab见!

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值