CSAPP-Lab1_datalab

Introduction


1.bitXor(int x, int y)

* bitXor - x^y using only ~ and & 
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1

思路:可以先将x、y同为1或0的位置找出来并置为0,剩余数置为1。x&y可以表示同为1的位置信息,~x&~y表示同为0的位置信息。那么x^y就是~(x&y)&~(~x&~y)

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

2.tmin(void)

* tmin - return minimum two's complement integer 
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1

思路:该题为返回最小的二进制补码整数,最小的有符号数,符号位为1,其余都是0。int占4字节,即32位,所以对1左移31位来构造最小补码。

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

3.isTmax(int x)

* isTmax - returns 1 if x is the maximum, two's complement number,
*     and 0 otherwise 
*   Legal ops: ! ~ & ^ | +
*   Max ops: 10
*   Rating: 1

思路:假设x是二进制补码的最大值,(x+1)为1<<31,那么~(x+1)^x就是0,再逻辑否即为1。但是由于 -1 = 0xFFFFFFFF。对其进行加1后,该操作数会被截断,使得结果为0x00000000,每一位刚好也和-1的每一位互补。因此,x = -1的情况是需要特判的。!(x+1) 即为1。 则该式在 x = -1 时一定为真,x != -1 时结局就取决于~(x+1)^x。故为 !(~(x+1)^x|!(x+1))

int isTmax(int x) {
  return !((~(x+1)^x)|!(x+1));
}

4.allOddBits(int x)

 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2

思路: 使用移位运算符构造出奇数位全1的数 y = 0xAAAAAAAA,如果与x相同,y&x就仍为y,然后再进行y^y然后返回其值的逻辑非得到1。若y与x不同,y&x不为y,再^操作后返回逻辑非得到0。

int allOddBits(int x) {
  int y = 0xAA + (0xAA << 8);
    y = y + (y << 16);
    return !((x&y)^y);
}

5.negate(int x)

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

思路:~x+x=-1;那么-x就为~x+1

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

6.isAsciiDigit(int x)

 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3

思路:这个函数让我们判断一个数是否位于0x30到0x39之间。分别进行判断,首先判断10位是否为3,我们可以利用右移运算符。然后,判断个位是否小于等于9。判断a小于等于b时,可以通过a + b <= 0来进行判断,也就是让二者相加,然后判断符号位。 y 在 0 到 9 之间,则 y - 10 < 0,由于符号限制,我们通过移位后判断符号位来作为条件3。由于不能用减法,可以通过y+~y=-1达到目的。

int isAsciiDigit(int x) {
     int y = x & 0xf; // 把最低位先拿出来
  	 return !((x >> 4) ^ 0x3) & !((0x9 + (~y + 1)) >> 31);
}

7.conditional(int x, int y, int z)

* conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3

思路:x=0时!x就是0x00000001,~(!x)+1为全一,x&z即为z,~x&y为0。x!=0时!x为0,~(!x)+1为全0,x&z为0,~x&y即为所求。

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

8.isLessOrEqual(int x, int y)

 * isLessOrEqual - if x <= y  then return 1, else return 0 
 *   Example: isLessOrEqual(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3

思路:当 y 与 x 同号时,x - y 不会溢出,只需判断x-y的符号。当 y 与 x 异号时,x - y 可能会溢出,这时只分别判断 y 和 x 的符号即可。首先利用移位操作,分别得到 x, y 的符号位,即int signx=(x >> 31) & 1;int signy = (y >> 31) & 1;int flag1=signx&(!signy),

正负signxsigny返回值flag1
x正y负010
x负y正101

在判断x-y时利用-y=~y+1;x≤y等价于x<y+1,因此x≤y时x-y-1的符号位为1。首先e用来判断x,y同号,然后((x+~y)>>31)判断符号位。最终flag1|flag2即为所求。

int isLessOrEqual(int x, int y) {
  int signx = (x >> 31) & 1;
    int signy = (y >> 31) & 1;
    int flag1 = signx & (!signy);
    int e = signx ^ signy; //判断同号
    int flag2 = ((!e) & ((x + ~y) >> 31) & 1);
    return flag1 | flag2;
}

9.logicalNeg(int x)

 * 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 

思路:仍然利用-x=~x+1;若x为0,则 x | (-x) 的符号位为0,将其右移31位依然为0,再+1即为1。若x不为0 则 x | (-x) 的符号位为1,将其右移31位可得到 0b11111...,即-1,再+1即为0。

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

10.howManyBits(int x)

* 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

思路:原理:对于正数,从高位到低位,找第一个位是1的(比如是n),再加上符号位,则最少需要n+1个位;对于负数,从高位到低位,找第一个位是0的(比如是n),则最少需要n位。int b16, b8, b4, b2, b1, b0;表示0~15、16~23、24~27、28~29、30、31的位置处是否含有1,如有,则对其赋值需要的位数。sign用以取符号位;然后如果x为正则不变,x为负则取反,之后只用找到含有1的位置即可。b16先看高16位是否含有1,若有则表示至少需要16位,所以给b16赋值为16(1 << 4 = 16)。若有1,则原数右移16位,因为上面已经确定是否至少需要16位(针对0~15);若没有1,则b16为0,x不用移位,继续往下面判断。b8看剩余位的高8位是否含有1,若有则表示至少还需要8位,给b8赋值为8。接着同理。最终b16+b8+b4+b2+b1+b0+1(加上符号位)。

int howManyBits(int x) {
  int b16, b8, b4, b2, b1, b0;
  int sign = x >> 31;
  x = (sign&~x)|(~sign&x); 

  b16 = !!(x >> 16) << 4;// 
  x =  x >> b16;

  b8 = !!(x >> 8) << 3; 
  x = x >> b8; 

  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;
}

11.floatScale2(unsigned uf)

* floatScale2 - 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

思路:先取出对应的符号s、尾数frac 和 阶码expr。unsigned s = uf >>31;unsigned expr =(uf >>23)&(0xFF);unsigned frac = uf &0x7FFFFF;分类讨论:(1)若f=0,则frac==0且expr==0,直接return 0。(2)如f为NaN或inifity,则expr ==0xFF,直接返回uf 。(3)expr==0,则frac <<1 并|上符号位s << 31。(4)expr ++ ,return (s<<31) | (expr <<23) | frac。

unsigned floatScale2(unsigned uf) {
        unsigned s = (uf >> 31)& 0x1;
        unsigned expr = (uf >> 23) & (0xFF);
        unsigned frac = uf & 0x7FFFFF;
    
        if(expr ==0 && frac == 0)
                return uf;
        if(expr == 0xFF)
                return uf;
        if(expr == 0)
        {
                frac <<= 1;
                return (s << 31) | frac;
        }
        expr++;
        return (s<<31) | (expr << 23) | frac;
}

12.floatFloat2Int(unsigned uf)

* floatFloat2Int - Return bit-level equivalent of expression (int) f
 *   for floating point argument f.
 *   Argument is passed as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point value.
 *   Anything out of range (including NaN and infinity) should return
 *   0x80000000u.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4

思路:该题为将浮点数转换为整数,若超出范围则返回0x80000000u。先取出对应的符号s、尾数frac 和 阶码expr。unsigned s = uf >>31;unsigned expr =(uf >>23) & (0xFF);unsigned frac = uf & 0x7FFFFF;分类讨论:(1)uf为0,直接返回0。(2)超出范围(Ini / nan),此时expr ==0xFF,直接return 1 << 31。(3)expr == 0,uf<1,同样返回0。(4)首先计算E:int E = expr -127; 和M:frac= frac |(1<<23);若E>31同样超出int范围,return 1<<31。若E<0, M * 2^E <1,return 0若E>=23,则M左移 E-23若E<23,则M右移 23-E。最后若s为1,则取反再+1,否则直接返回M。

int floatFloat2Int(unsigned uf) {
 unsigned s = uf >> 31;
        unsigned expr = (uf >> 23) & (0xFF);
        unsigned frac = uf & 0x7FFFFF;
        if(expr == 0 && frac == 0)
                return 0;
        if(expr == 0xFF)
                return 1 << 31;
        if(expr == 0)
        {
                return 0;
        }
        int E = expr - 127;
        frac = frac | (1 << 23);
        if(E >31)
                return 1 << 31;
        else if(E < 0)
                return 0;
        else if(E >= 23)
        {
                frac <<= (E - 23);
        }
        else
        {
                frac >>= (23 - E);
        }
        if(s)
                return ~frac + 1;
        return frac;
}

13.floatPower2(int x)

 * floatPower2 - Return bit-level equivalent of the expression 2.0^x
 *   (2.0 raised to the power x) for any 32-bit integer x.
 *
 *   The unsigned value that is returned should have the identical bit
 *   representation as the single-precision floating-point number 2.0^x.
 *   If the result is too small to be represented as a denorm, return
 *   0. If too large, return +INF.
 * 
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 
 *   Max ops: 30 
 *   Rating: 4

思路:分类讨论:(1)可表示的最小范围是阶码全为0,尾数只有最后一位是1,x<-149即2^-(127+23),则x<-149时,计算结果太小,无法表示,直接返回0。(2)可表示的最大范围是阶码全为1,尾数全为1,即1.11111...(2) * 2 ^(127),对于阶码全为1的情况,直接返回INF,即 return 0xFF << 23。(3)阶码全为0,指数对应为1-127 = -126,可表示的二进制位数就是 x + 126 +23 (此时-149<x<-126),return 1 << (x + 126 + 23)(4) -126<= x <=127的情况,计算阶码 expr = x - 127,return expr << 23 即可。

该题如果显示超时可以通过在driver.pl文件里两个btest相关的命令加上- T 30解决。

unsigned floatPower2(int x) {
    if(x < -149)
        return 0;
    else if(x < -126)
        return 1 << (x + 149);
    else if(x <= 127)
        return (x + 127) << 23;
    else
        return (0xFF) << 23;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值