2021-2-3 csapp:datalab

int类型规则:
    1. 只允许使用0-0xff的整数
    2. 只允许存在函数参数和局部变量(无全局变量)
    3.可使用的一元运算符! ~
    4.可使用的二元运算符& ^ | << >>
    5.只允许使用整数, 不可以使用联合体数组等
    6.不允许使用任何控制结构
    7.不允许使用任何宏或者定义宏
    8.不允许定义任何/调用函数
    
您可以假设您的机器:
    1.使用2s补码(32位整数表示)。
    2.算术执行右移。
    3.如果移位量小于0或大于31,则在移位时具有不可预测的行为。
 

Rate1:

一、bitXor(只允许使用~和|)
int bitXor(int x, int y) {
    
    
    return (~(x&y))&(~(~x&~y));    
}

思路:
(君离散数学本当上手)

二、timin(返回最小值)
int tmin(void) {
    
    
  return (1<<31);
}

思路: 一开始看到没有参数懵逼的说, 然后看了下攻略发现直接返回一个数就行了, 那么可以考虑直接位移就行了,0xff<<24什么的也是可以哒!

三、isTmax(是否为最大补码)

这题不会看, 所以知乎大佬的:

int isTmax(int x) {
    
    
  int i = x+1;
  x=x+i;
  x=~x;
  i=!i;
  x=x+i;
  return !x;
}

(照搬知乎李明岳大佬)

Rate2:

四:allOddBits(判断参数x是否奇数位全为1)
int allOddBits(int x){
    
    
    int mask=(0xAA)+(0xAA)<<8;
    mask=mask+(mask<<16);
    return !((~x&mask)^mask);
} 

思路: 一开始思路是通过16次<<再+01操作构造的, 然后想想太傻逼了, 就去知乎学了一下, 顺便晓得了自己构造的码叫掩码, 然后就很简单了, 先获取所有奇数位再异或一下, 然后非就行了(题目还看错了, 我还以为偶数位要求全0的=。=)

五:negate(不用-取反)

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

思路: 阿贝群

Rate3:

六:isAsciiDigit(j检测是否为ASCII)

知乎大佬写的:

int isAsciiDigit(int x) {
    
      
    int sign=1<<31;
    int lowest=~0x30,highest=~(sign|0x39);
    lowest=sign&(lowest+1+x)>>31;
    highest=sign&(highest+x)>>31;
    return !(lowest|highest);  
}

自己的思路想打表的, 然后运算符超出限制了(

七:conditional(实现 : ? )

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

思路: x为正得到x=00,x为非正得到x=0xff, &0代表清空多少位,&1代表保留多少位 |或一下,反正前后总有一个是0,|的话真的就和2选1一样

八:isLessOrEqual(实现 <= )

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

思路:(~x+1)得到-x, y-x看正负, 再算数左移之后!一下即可
 

快全线崩溃的Rate4:

九:logicalNeg(计算!而不用!)

int logicalNeg(int x) {
    
    
  return ((x|(~x+1))>>31)+1;
}

思路: 首先要记得-x为~x+1, 只有在x=0的情况下,x=-x, 则x| ~x会得到0, 其他情况都会在符号位因为正负的关系得到0和1, 则|之后会产生1, 之后我们再算术右移31再+1即可

十:howManyBits(计算有多少位)

知乎大佬的思路:

int howManyBits(int x) {
    
    
  int b16,b8,b4,b2,b1,b0;
  int sign=x>>31;
  x = (sign&~x)|(~sign&x);//如果x为正则不变,否则按位取反(这样好找最高位为1的,原来是最高位为0的,这样也将符号位去掉了)
  b16 = !!(x>>16)<<4;//高十六位是否有1
  x = x>>b16;//如果有(至少需要16位),则将原数右移16位
  b8 = !!(x>>8)<<3;//剩余位高8位是否有1
  x = x>>b8;//如果有(至少需要16+8=24位),则右移8位
  b4 = !!(x>>4)<<2;//同理
  x = x>>b4;
  b2 = !!(x>>2)<<1;
  x = x>>b2;
  b1 = !!(x>>1);
  x = x>>b1;
  b0 = x;
  return b16+b8+b4+b2+b1+b0+1;//+1表示加上符号位
}

只能说过于精巧(照搬知乎李明岳大佬)

十一: floatScale2(2.0乘浮点数)

unsigned floatScale2(unsigned uf) {
    
    
  int exp = (uf&0x7f800000)>>23;//exp为阶码,uf&0x7f800000只保留uf的阶码,并且逻辑右移23位移除尾数 
  int sign = uf&(1<<31);//sign为 阶符 
  if(exp==0) return uf<<1|sign;//如果阶码为0(非格式化),则2^(-2^7)*M,而非格式化中f=M所以只要做到尾数f整体左移1即可 
  if(exp==255) return uf;//如果exp ==0xff则为NaN,直接返回 
  exp++;//用于公式x=(-1)*M*2^E ,M=1+f,E=en...e0-Bias,则E++就可以做到2^(E+1) 
  if(exp==255) return 0x7f800000|sign;//返回无穷 
  return (exp<<23)|(uf&0x807fffff);//补上尾数 
}

思路写在注释了, 部分情况没考虑到, 看了知乎大佬的

十二:floatFloat2Int(浮点数转换为整数)

int floatFloat2Int(unsigned uf) {
    
    
  int s_    = uf>>31;
  int exp_  = ((uf&0x7f800000)>>23)-127;
  int frac_ = (uf&0x007fffff)|0x00800000;
  if(!(uf&0x7fffffff)) return 0;

  if(exp_ > 31) return 0x80000000;
  if(exp_ < 0) return 0;

  if(exp_ > 23) frac_ <<= (exp_-23);
  else frac_ >>= (23-exp_);

  if(!((frac_>>31)^s_)) return frac_;
  else if(frac_>>31) return 0x80000000;
  else return ~frac_+1;
}

没想出来, 看的李明岳大佬的

十三: floatPower2(2.0的指数运算)

unsigned floatPower2(int x) {
    
    
    int Nan=0xff<<23;
	int result=x+127;
	if(result<=0)return 0;
	if(result>=255)return Nan;
	return result<<23; 
}

思路:首先表示2.0, M*2^E, 则有M = 1+f, 所以2.0为(1)*2 ^1, 尾数全为0即可,而2.0的指数在阶码可直接体现, 所以用127+x即可得到2.0 ^x的表示, 剩下的就是考虑范围了, 如果127+x>=255则返回越界就好, 如果是小数则直接返回0就好, 这是题目所要求的

总结:

    datalab总共做了三天, 其中有四道题完全不会, 还有一道题考虑的不够周到, r4难度很多想了大半天也想不出来= =, 所以后来做的有点崩溃, 希望以后复习的时候能多康康吧, 这个lab还是很能锻炼人对浮点数和整数的理解的, 虽然浮点数过了段时间还是要忘(悲

猜你喜欢

转载自blog.csdn.net/eeeeeight/article/details/113602858
今日推荐