CS:APP Data Lab实验详解

目录

1.bitOr 

2.evenBits

3.isTmin

 4.allEvenBits

5.anyEvenBit

6.fitsBits

7.float_neg

8.isAsciiDigit

9.isLess

10.multFiveEighths

11.replaceByte

12.bitParity

13.float_half

14.ilog2

15.sm2tc

1.bitOr 

使用运算符个数:4

题目:用~和&实现|

解析:

按位取反运算符的逻辑:原数的补码按位取反,取按位取反后的数的反码,再取补码,得到的即为按位取反后的数

可知,~x = -(x+1)

德摩根定律:~(x&y) = (~x)|(~y)         ~(x|y) = (~x)&(~y)

则x|y = ~(~(x|y)) = ~((~x)&(~y))

/* 
 * bitOr - x|y using only ~ and & 
 *   Example: bitOr(6, 5) = 7
 *   Legal ops: ~ &
 *   Max ops: 8
 *   Rating: 1
 */
int bitOr(int x, int y) {
  return ~((~x) & (~y));
}

2.evenBits

使用运算符个数:4

题目:返回一个32位的二进制数,其偶数位均为1

解析:

需要注意的是,最低位为0位,即返回的数为010101……0101

题目要求取的数大小不能超过255,则先取a = 0x55,一个8位二进制数

将a左移8位,后面补8个0,与0x55按位或(有1结果为1),得到16位0101……的二进制数

同理,左移16位按位或本身,得到题目要求的32位数

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

3.isTmin

使用运算符个数:6

题目:如果x是32位二进制能表示的最小数,返回1,否则返回0

解析:

由题可知,如果x是最小数,那么x = 10000……000,则x满足x == ~x+1

判断两数相等使用异或操作(不同才为1)

同时,需要排除同样满足条件的0x00000000

/*
 * isTmin - returns 1 if x is the minimum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmin(int x) {
  return !((x ^ (~x + 1)) | (!x));
}

其他方法:4

int evenBits(void) {
  int x = 85; 
  x = x | (x << 8);
  x = x | (x << 16);
  return x;
}

 4.allEvenBits

使用运算符个数:7

题目:如果x偶数位全为1,返回1

解析:

取y = 0xAA,即10101010,同第二题操作,先按位或左移8位,再按位或左移16位,得到32位的101010……1010

y|x,如果得到32位全1,则x的偶数位全1,~(x|y)为0,!~(x|y)为1

/* 
 * allEvenBits - return 1 if all even-numbered bits in word set to 1
 *   Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allEvenBits(int x) {
  int y = 0xAA;
  y = y | y << 8;
  y = y | y << 16;
  return !~(x | y);
}

5.anyEvenBit

使用运算符个数:7

题目:如果x有任何一位偶数位为1,返回1

解析:

构造y = 0x55555555,即010101……0101

x&y,如果x有偶数位为1,结果不为0,如果x偶数位全部为0,结果为0

!!(x&y),两次!,为了得到单独的1或0

/* 
 * anyEvenBit - return 1 if any even-numbered bit in word set to 1
 *   Examples anyEvenBit(0xA) = 0, anyEvenBit(0xE) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int anyEvenBit(int x) {
  int y = 0x55 | 0x55 << 8;
  y = y | y << 16;
  return !!(x & y);
}

6.fitsBits

使用运算符个数:7

题目:如果x可以用n位二进制数表示,返回1,否则返回0

解析:

~0为0xFFFFFFFF,值为-1,a = n+(~0)指a = n-1

b = x>>a,将x右移n-1位,正数移后值为0,负数为-1

(!b|(!(b+1))),判断b是否全为0或全为1,如果全为0或全为1,返回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 a = n + (~0);
  int b = x >> a;
  return (!b | !(b + 1));
}

7.float_neg

使用运算符个数:3

题目:返回uf的负数,如果uf是NaN,返回其本身

解析:

单精度浮点数用IEEE754存储,即将符号位取反就得到uf的负数

NaN用IEEE756表示时,符号位为0或1,阶码全为1,尾数非零

如果uf&0x7FFFFFFF>0x7F800000,uf为NaN,返回其本身

其他数,uf^0x80000000,将符号位取反后返回

/* 
 * 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) {
 if((uf & 0x7fffffff) > 0x7f800000)
   return uf;
 return uf ^ 0x80000000;
}

8.isAsciiDigit

使用运算符个数:12

题目:如果x的值在0x30到0x39之间,返回1

解析:

判断x-0x30和0x39-x的正负,减法用-x = (~x)+1实现

c = 1<<31,得到32位二进制最小数,只有最高位是1

(!(a&c))&(!(b&c)),如果a和b均为整数,&c得0,!得1,即只有a、b均为整数返回1

/* 
 * 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
 */
int isAsciiDigit(int x) {
  int a = x + (~0x30 + 1);
  int b = 0x39 + (~x + 1);
  int c = 1 << 31;
  return (!(a & c)) & (!(b & c));
}

其他方法:8

int isAsciiDigit(int x) {
	return (!((x + ~0x2F) >> 31)) & ((x + ~0x39) >> 31);
}

9.isLess

使用运算符个数:14

题目:如果x

解析:

a = ((x&~y)>>31)&1,判断x为负数,y为正数的情况,如果x为负y为正,a = 1

b = ~((x^y)>>31),x和y符号相同时b = 1,否则b = 0

(x+~y+1)>>31,获取x-y的符号位,当两数符号位相同且x-y为负数时,结果为1

/* 
 * isLess - if x < y  then return 1, else return 0 
 *   Example: isLess(4,5) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 24
 *   Rating: 3
 */
int isLess(int x, int y) {
  int a = ((x & ~y) >> 31) & 1;
  int b = ~((x ^ y) >> 31); 
  return a | ((b & ((x + ~y + 1) >> 31)) & 1);
}

其他方法:5

int isLess(int x, int y) {
    int not_y = ~y;
	long long lltemp=x;
	return  1+((y+~lltemp)>>63);
}

10.multFiveEighths

使用运算符个数:6

题目:将x*5/8,并向0舍入

解析:

x = x+(x<<2),x<<2为x*4,再加1,即为x*5

x>>3为x/8,对于正数来说满足向0舍入,但对于负数来说,如果移出部分非0,需要给整数部分加1才是向0舍入

将x>>31得到符号位,并且&7(7的二进制位000……0111)

如果x是正数,结果为0,x直接右移3位

如果x是负数,结果为x+7,相当于给高位进1,之后再右移3位

/*
 * multFiveEighths - multiplies by 5/8 rounding toward 0.
 *   Should exactly duplicate effect of C expression (x*5/8),
 *   including overflow behavior.
 *   Examples: multFiveEighths(77) = 48
 *             multFiveEighths(-22) = -13
 *             multFiveEighths(1073741824) = 13421728 (overflow)
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 3
 */
int multFiveEighths(int x) {
  x = x + (x << 2);
  return (x + (x >> 31 & 7)) >> 3;
}

11.replaceByte

使用运算符个数:7

题目:将x的第n个字节用c代替

解析:

n<<3,即n*8(一个字节八个比特位),a = 0xFF<<(n<<3),将第n个字节变为全1

c <<= (n<<3),将c移到第n个字节的位置

x&(~a),将x的第n个字节清零,后按位或c(有1结果为1)

/* 
 * replaceByte(x,n,c) - Replace byte n in x with c
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
 *   You can assume 0 <= n <= 3 and 0 <= c <= 255
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 3
 */
int replaceByte(int x, int n, int c) {
  int a = 0xff << (n << 3);
  c <<= (n << 3);
  return (x &(~a)) | c;
}

其他方法: 6

int replaceByte(int x, int n, int c) {
    int n_dis = n << 3;
    int clear_mask = 0xFF << n_dis;
    int new_mask = c << n_dis;
    return (x & ~clear_mask) | new_mask;
}

12.bitParity

使用运算符个数:11

题目:如果x含有奇数个0,返回1

解析:

x ^= x>>16,将x的高16位和低16位异或(不同才为1),即如果两位相同,是偶数个,消掉

同理,直到x剩下1位,如果有奇数个0,x的最低位 != 0,如果是偶数个0,x的最低位 = 0

返回x&1(只取x最低位

/*
 * bitParity - returns 1 if x contains an odd number of 0's
 *   Examples: bitParity(5) = 0, bitParity(7) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 4
 */
int bitParity(int x) {
  x ^= x >> 16;
  x ^= x >> 8;
  x ^= x >> 4;
  x ^= x >> 2;
  x ^= x >> 1;
  return x & 1;
}

13.float_half

使用运算符个数:30

题目:返回0.5*uf

解析:

对于0,无穷大和NaN,直接返回其本身

对于非规格化数,尾数右移1位,需要考虑舍入问题

对于规格化数,阶码-1,如果-1后为0,变成非规格化数,尾数最高位需要补1,最低位需要移出

尾数+1,向偶数舍入

/* 
 * float_half - Return bit-level equivalent of expression 0.5*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_half(unsigned uf) {
    int a=0xff<<23;
    int b=!((uf&3)^3);
    int sign=uf&(0x80<<24);
    int exp=uf&a;
    int frac=(uf&((((0xff<<8)+0xff)<<7)+0x7f));
    if(exp==a)
        return uf;
    if(exp==(0x80<<16))
        return sign|(b+((uf&(~(0x80<<24)))>>1));
    if(exp==0x0)
        return sign|((frac>>1)+b);
    
    return (((exp>>23)-1)<<23)|sign|frac;
}

其他方法:7

unsigned float_half(unsigned uf) {
  	unsigned half = uf >> 1;
	int Sgn = 0;
	switch (uf >> 23)
	{
		case (0x000):case (0x001): break;
		case (0x100):case (0x101):{Sgn = 0xc0000000; break;}
		case (0x0ff):case (0x1ff): return uf;
		default: return uf - 0x800000;
	}
	return Sgn ^ (half + (uf & half & 1));
}

14.ilog2

使用运算符个数:24

题目:返回以2为底x的对数,向下取整

解析:

若x = 00010000,结果为4;若x = 00010001,结果为4.1699……,向下取整后为4

问题转换为求x最高1位的位数(位数是从0到31)

用一个5位二进制数b4b3b2b1b0来表示

如果高16位有1,b4 = 1,如果高16位的高8位有1,b3 = 1,如果高16位的高8位的高4位有1,b2 = 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) {
  int a = 0;
  int b = !(x >> 16);
  int n = b << 4;
  a = n;
  x = x << n;
  b = !(x >> 24);
  n = b << 3;
  a = a + n;
  x = x << n;
  b = !(x >> 28);
  n = b << 2;
  a = a + n;
  x = x << n;
  b = !(x >> 30);
  n = b << 1;
  a = a + n;
  x = x << n;
  a = a + !(x >> 31);
  return 32 + ~a;
}

15.sm2tc

使用运算符个数:5

题目:将原码转换为补码形式

解析:

a = (x>>31),取x的符号位

x^a,若x为正数,结果不变,若x为负数,结果为x取反

(1<

/* 
 * sm2tc - Convert from sign-magnitude to two's complement
 *   where the MSB is the sign bit
 *   Example: sm2tc(0x80000005) = -5.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 4
 */
int sm2tc(int x) {
  int a = (x >> 31);
  return (x ^ a) + ((1 << a)^ 1);
}

你可能感兴趣的:(CS:APP实验,c++,开发语言,经验分享)