CSAPP 3e : Data lab
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSAPP 3e : Data lab相关的知识,希望对你有一定的参考价值。
/* * CS:APP Data Lab * * <Please put your name and userid here> * * bits.c - Source file with your solutions to the Lab. * This is the file you will hand in to your instructor. * * WARNING: Do not include the <stdio.h> header; it confuses the dlc * compiler. You can still use printf for debugging without including * <stdio.h>, although you might get a compiler warning. In general, * it‘s not good practice to ignore compiler warnings, but in this * case it‘s OK. */ /* * bitAnd - x&y using only ~ and | * Example: bitAnd(6, 5) = 4 * Legal ops: ~ | * Max ops: 8 * Rating: 1 */ int bitAnd(int x, int y) { return ~(~x|~y); //简单,不解释。 } /* * getByte - Extract byte n from word x * Bytes numbered from 0 (LSB) to 3 (MSB) * Examples: getByte(0x12345678,1) = 0x56 //指定n,获取第n个字节上的数字。0<=n<=3。 * Legal ops: ! ~ & ^ | + << >> * Max ops: 6 * Rating: 2 */ int getByte(int x, int n) { n=n<<3; //n*=8,因为每个字节占8个二进制位。 x=x>>n&0xff; //x右移n位,即把需要获取的字节移到了最低号位,再用&操作取得目标字节(其余位置0)。 return x; } /* * logicalShift - shift x to the right by n, using a logical shift //用算数移位实现逻辑移位(右)。 * Can assume that 0 <= n <= 31 * Examples: logicalShift(0x87654321,4) = 0x08765432 * Legal ops: ! ~ & ^ | + << >> * Max ops: 20 * Rating: 3 */ int logicalShift(int x, int n) { x=x>>n; //算数右移。 x=~((~0)<<(~n+32+1))&x; //将因算数右移可能补1的n个位置0。(~n+32+1)实现(32-n),~n等于(-n-1)。 return x; } /* * bitCount - returns count of number of 1‘s in word //要求计算参数值得二进制位中1的个数。 * Examples: bitCount(5) = 2, bitCount(7) = 3 //用二分法。每次相加二分移位前后的值,则在相应的n个位上存储了该次 * Legal ops: ! ~ & ^ | + << >> //二分中1的个数。eg:第一次移位操作移了移位,相加得的是相邻两个位中 * Max ops: 40 //1的个数,最高值位2(b 10),需要两个位进行存储相加值。所以x&5, * Rating: 4 //因为5二进制为 b 0101。第二次操作移2位,每一个计算单元(2+2=4个位上1的个数)最大值为4(b 100) */ //所以有x&3,3=(b 0011); !重点应该发现x&(01)到(0011),再到(00001111)的变化,分别对应于二分移n位 int bitCount(int x) { //的操作。 x=(x&0x55555555)+(x>>1&0x55555555); x=(x&0x33333333)+(x>>2&0x33333333); x=(x&0x0f0f0f0f)+(x>>4&0x0f0f0f0f); x=(x&0x00ff00ff)+(x>>8&0x00ff00ff); x=(x&0x0000ffff)+(x>>16&0x0000ffff); /*x=(x+(x>>4))&0x0f0f0f0f; x = x + (x >> 8); //此处是网上找到的方法,其实是一样的。这里后边没有0x00ff00ff是因为可以省略了。 x = x + (x >> 16); //不过需要最后x&0x3f的操作消去从第8位开始可能存在的1(二进制中)。 x=x&0x3f;*/ return x; } /* * bang - Compute !x without using ! * Examples: bang(3) = 0, bang(0) = 1 //如果x!=0,x=(x|(~x+1))符号位为1,只有x==0时才为0;(注意这里说的是 * Legal ops: ~ & ^ | + << >> //符号位)。 * Max ops: 12 * Rating: 4 */ int bang(int x) { x=(~((x|(~x+1))>>31))&1; return x; } /* * tmin - return minimum two‘s complement integer //返回int的最小值。即0x80000000; * Legal ops: ! ~ & ^ | + << >> * Max ops: 4 * Rating: 1 */ int tmin(void) { return (1<<31); } /* * 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 shif=(~n+1+32); //shif=(32-n); int def=~(~0<<n); //def=1左移n位,但是不补0而是补1,比如得def=0x0000ffff; x=!!(x^((x<<shif)>>shif&def)); return x; } /* * divpwr2 - Compute x/(2^n), for 0 <= n <= 30 * Round toward zero * Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2 * Legal ops: ! ~ & ^ | + << >> * Max ops: 15 * Rating: 2 */ int divpwr2(int x, int n) { //做这题的时候没有想到偏置量这个东西,后来在网上查了才知道的。 //全0或者全1 int signx = x >> 31; int mask = (1 << n)-1 ;//+ (~0);//得到2^n - 1 int bias = signx & mask;//如果x是正数,则bias为0,即不用加,直接移位 //如果x为负数,加上偏置量之后再移位 return (x + bias) >> n; } /* * negate - return -x * Example: negate(1) = -1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 2 */ int negate(int x) { return ~x+1; } /* * isPositive - return 1 if x > 0, return 0 otherwise * Example: isPositive(-1) = 0. * Legal ops: ! ~ & ^ | + << >> * Max ops: 8 * Rating: 3 */ int isPositive(int x) { x=!(x>>31&0x1|!x); return x; } /* * 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 signx=x>>31;//如果x(y)为正数,则signx(signy)等于0;否则等于-1,即0xffffffff; int signy=y>>31; int same=((x+(~y))>>31)&(!(signx^signy)); //当x,y同号,求if x<=y; int differ=(!(y>>31))&(signx^signy); //当x,y异号,求if x<=y;异号的话其实y是正数则x<=y成立。 return same|differ } /* * ilog2 - return floor(log base 2 of x), where x > 0 * Example: ilog2(16) = 4 * Legal ops: ! ~ & ^ | + << >> //理解方法是,在参数x的二进制位中,最左边的1是在第n位,则log(x)=n-1; * Max ops: 90 //如:16的二进制是10000,最左边1在第5位,所以log(16)=5-1=4;也可以看到1右边有4个0; * Rating: 4 */ int ilog2(int x) { int bitsNumber=0; bitsNumber=(!!(x>>16))<<4; bitsNumber=bitsNumber+((!!(x>>(bitsNumber+8)))<<3); bitsNumber=bitsNumber+((!!(x>>(bitsNumber+4)))<<2); bitsNumber=bitsNumber+((!!(x>>(bitsNumber+2)))<<1); bitsNumber=bitsNumber+((!!(x>>(bitsNumber+1)))); bitsNumber=bitsNumber+((!!bitsNumber)+(~0)+(!(1^x))); return bitsNumber; } /* * 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) { unsigned result; unsigned tmp; result=uf ^ 0x80000000; //将符号位改反 tmp=uf & (0x7fffffff); if(tmp > 0x7f800000)//此时是NaN result = uf; return result; } /* * float_i2f - Return bit-level equivalent of expression (float) x 返回int x的浮点数的二进制形式。 * Result is returned as unsigned int, but 返回的是unsigned型但是表示的时二进制单精度形式 * it is to be interpreted as the bit-level representation of a * single-precision floating point values. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ unsigned float_i2f(int x) { //浮点这里是直接“借鉴”了,看着好晕。。。 unsigned shiftLeft=0; unsigned afterShift, tmp, flag; unsigned absX=x; unsigned sign=0; //special case if (x==0) return 0; //if x < 0, sign = 1000...,abs_x = -x if (x<0) { sign=0x80000000; absX=-x; } afterShift=absX; //count shift_left and after_shift while (1) { tmp=afterShift; afterShift<<=1; shiftLeft++; if (tmp & 0x80000000) break; } if ((afterShift & 0x01ff)>0x0100) flag=1; else if ((afterShift & 0x03ff)==0x0300) flag=1; else flag=0; return sign + (afterShift>>9) + ((159-shiftLeft)<<23) + flag; } /* * float_twice - Return bit-level equivalent of expression 2*f for * floating point argument f. 返回 以unsinged表示的浮点数二进制的二倍的二进制unsigned型 * 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_twice(unsigned uf) { unsigned f = uf; if ((f & 0x7F800000) == 0) // { //左移一位 f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f); } else if ((f & 0x7F800000) != 0x7F800000) { f =f + 0x00800000; } return f; }
以上是关于CSAPP 3e : Data lab的主要内容,如果未能解决你的问题,请参考以下文章