CSAPP:位操作實現基本運算


@

實驗要求

給出15個函數,規定了實現每個函數需要的邏輯和算術操作符(規定數量)。
只能使用規定的操作符! ˜ & ˆ | + << >>
1-12題不能使用循環或者條件語句
不能使用超過8位的常數(ff)

轉載請注明出處:https://www.cnblogs.com/ustca/p/11740382.html

實現代碼

1、pow2plus1

/*
 * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
*/
int pow2plus1(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     return (1 << x) + 1;
}

2、pow2plus4

/*
* pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
*/
int pow2plus4(int x) {
	/* exploit ability of shifts to compute powers of 2 */
	int result = (1 << x);
	result += 4;
	return result;
}

3、bitXor

/*   bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {
	return (~(x&y))&(~(~x&~y));//列出真值表
}

4、tmin

/*   tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
	return 1<<31;//0x80000000
}

5、isTmax

/*   isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x) {
	return !(x+x+2) & !!(~x);//x+1+x+1溢出並且非全一
	//x:		0111 1111 1111 1111 1111 1111 1111 1111
	//x+1:	1000 0000 0000 0000 0000 0000 0000 0000
	//x+1+x:	1111 1111 1111 1111 1111 1111 1111 1111
	//x+1+x+1:0000 0000 0000 0000 0000 0000 0000 0000
}

6、allOddBits

/*   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
 */
int allOddBits(int x) {	
	x = (x>>16) & x;	
	x = (x>>8) & x;		
	x = (x>>4) & x;		
	x = (x>>2) & x;		
	return (x>>1)&1;	
	// &運算符的“歸一性”
	//1010 1010 1010 1010 1010 1010 1010 1010
	//0000 0000 0000 0000 1010 1010 1010 1010
	//0000 0000 0000 0000 0000 0000 1010 1010
	//0000 0000 0000 0000 0000 0000 0000 1010
	//0000 0000 0000 0000 0000 0000 0000 0010 
	// 可以反推理解:后四位四次翻轉得第一行
	// 只要倒數第二位為1成立,反推后所有的奇數位都為1
}

7、negate

/*   negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
	return ~x+1;	//帶符號位取反加一即為相反數
}

8、isAsciiDigit

/*   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) {
	// 0x30 = 0011 0000b   0x39 = 0011 1001b
	int a = (x>>4) ^ 0x3;	// 判斷5、6位是否全1
	int b0 = (x>>3) & 1;	// 判斷第4位是否為1
	int b1 = (x>>2) ^ 1;	// 判斷第3位是否為1
	int b2 = (x>>1) ^ 1;	// 判斷第2位是否為1
	return (!a) & ((!b0) | (b0&b1&b2)); 
	// 如果5、6位全1 且 (4位為0或4位為1,2、3位為0)
}

9、conditional

/*   conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z) {
	x = !x;	// 將x設置為0或1
	x = (x<<31)>>31; // 將x的0或1拓展到32位全0或全1
	return (~x&y) | (x&z); // x為真則~x全1返回y,為假則x全1返回z
}

10、isLessOrEqual

/*   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 z,s,sx,sy;
	sx = (x>>31)&1;	// 	取x的符號位
	sy = (y>>31)&1; //	取y的符號位
	z = x + ~y + 1; //	z = x-y
	s =  ((z>>31) & 1) | (!(z^0));
	// 取z的符號位,s為真時x<y或者z全0(x==y)
	return  ((!(sx^sy))&s) | (sx&(!sy));
	// xy同號且z<=0 或 x<=0 y>=0
}

11、logicalNeg

/*   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) {
	// |運算符的“分裂性”
	x |= x>>16; // 若高16位有1,則傳遞給低16位的對應位
	x |= x>>8;	// 若低16位的高8位有1,則傳遞給低8位的對應位
	x |= x>>4;	// 若低8位的高4位有1,則傳遞給低4位的對應位
	x |= x>>2;	// 若低4位的高2位有1,則傳遞給低2位的對應位
	x |= x>>1;	// 若低2位的高1位有1,則傳遞給最低1位
	x ^= 1; 	// 只要x包含1,則必定會導致此時的x為1,x^=1即取反
	return x&1; 
}

12、howManyBits

/*  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 s,c1,c2,c3,c4,c5,c6;
	int cnt = 0;	// 	計數
	s = (x>>31)&1;	//	符號位
	x = ((s<<31)>>31) ^ x; // 取反x
	s = !!(x>>16);	// 判斷高16位是否有1,有則s為1
	c1 = s<<4;		// 若高16位有1,則低16位可以計數16
	x >>= c1;		// 右移將已經計數的位移除,c1若為0,則用折半的長度判斷
	s = !!(x>>8);	// 用8位的長度去判斷,有效位的個數計入c2
	c2 = s<<3;
	x >>= c2;
	s = !!(x>>4);	// 用4位的長度去判斷,有效位的個數計入c3
	c3 = s<<2;
	x >>= c3;
	s = !!(x>>2);	// 用2位的長度去判斷,有效位的個數計入c4
	c4 = s<<1;
	x >>= c4;
	s = !!(x>>1);	// 用1位的長度去判斷,有效位的個數計入c5
	c5 = s;
	x >>= c5;
	c6 = !!x;		// 判斷最低位是否為1
	cnt = c1+c2+c3+c4+c5+c6+1;	// 將每次獲得的低位有效位相加,再加1位符號位
	return cnt;
}

13、floatScale2

/*   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
 */
unsigned floatScale2(unsigned uf) {
	unsigned f = uf;
	if ((f & 0x7F800000) == 0)// 如果階碼為0
		f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f); 
		// 尾數不為0則尾數左移1位,尾數第1位為1則階碼加1,尾數為0則uf為0返回0
	else if ((f & 0x7F800000) != 0x7F800000)// 如果階碼不為0,且非全1
		f = f + 0x00800000;// 階碼加1
	return f;
}

14、floatFloat2Int

/*   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
 */
int floatFloat2Int(unsigned uf) {
	unsigned INF = 1<<31;	// INF = MaxInt+1
	int e = (uf>>23) & 0xff;// 階碼
	int s = (uf>>31) & 1;	// 符號位
	if (uf == 0) return 0;
	uf <<= 8;		// 左移保留至階碼最后1位
	uf |= 1<<31;	// 階碼最后一位設為1
	uf >>= 8;		// 高八位全0
	e -= 127;		// 階數
	if ((uf & 0x7f80000) == 0x7f80000 || e >= 32)
		return INF; // 超過int范圍返回INF
	if (e < 0) // 小數返回0
		return 0;
	if (e <= 22) // 位數小於等於22位,尾數位右移
		uf >>= 23-e;
	else 
		uf <<= e-23; // 尾數大於22位,尾數為左移
	if (s) 
		uf = ~uf + 1;// 若原uf為負數,則對此處的正數uf取反加1得其相反數
	return uf;
}

15、floatPower2

/*   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
 */
unsigned floatPower2(int x) {
	unsigned INF = 0xff << 23; // 階碼全1
	int e = 127 + x;	// 得到階碼
	if (x < 0) // 階數小於0直接返回0
		return 0;
	if (e >= 255) // 階碼>=255直接返回INF
		return INF;
	return e << 23;
	// 直接將階碼左移23位,尾數全0,規格化時尾數隱藏有1個1作為底數
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM