CS:APP Data Lab
阿新 • • 發佈:2018-11-11
使用方法
1.編寫bits.c,然後編譯
unix> ./dlc -e bits.c
dlc:bits.c:147:bitXor: 8 operators dlc:bits.c:158:tmin: 1 operators dlc:bits.c:169:isTmax: 7 operators dlc:bits.c:185:allOddBits: 10 operators dlc:bits.c:196:negate: 2 operators dlc:bits.c:214:isAsciiDigit: 14 operators dlc:bits.c:226:conditional: 7 operators dlc:bits.c:243:isLessOrEqual: 18 operators dlc:bits.c:261:logicalNeg: 12 operators dlc:bits.c:306:howManyBits: 37 operators dlc:bits.c:327:floatScale2: 9 operators dlc:bits.c:355:floatFloat2Int: 23 operators dlc:bits.c:375:floatPower2: 5 operators
2.執行和評分 (每次修改bit.c後都要重新編譯btest)
unix> make btest && ./btest
Score Rating Errors Function 1 1 0 bitXor 1 1 0 tmin 1 1 0 isTmax 2 2 0 allOddBits 2 2 0 negate 3 3 0 isAsciiDigit 3 3 0 conditional 3 3 0 isLessOrEqual 4 4 0 logicalNeg 4 4 0 howManyBits 4 4 0 floatScale2 4 4 0 floatFloat2Int 4 4 0 floatPower2 Total points: 36/36
參考程式碼
整數
bitXor: 計算x^y
/* 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) & ~(~y&x)); // x^y = (~x&y) | (x^~y)
}
tmin: 返回最小的32位有符號數
/* * tmin - return minimum two's complement integer * Legal ops: ! ~ & ^ | + << >> * Max ops: 4 * Rating: 1 */ int tmin(void) { return 1<<31; }
isTmax: 判斷一個數是不是最大的32位有符號數
/*
* 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+x+2 == 0
}
allOddBits: 判斷二進位制表示中是否所有的奇數位都是1
/*
* 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
*/
int allOddBits(int x) {
x = (x>>16) & x;
x = (x>>8) & x;
x = (x>>4) & x;
x = (x>>2) & x;
return (x>>1)&1;
}
negate: 返回-x
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
* 返回-x
*/
int negate(int x) {
return ~x+1;
}
isAsciiDigi: 判斷一個數是否在[0x30,0x39]範圍內
/*
* 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>>4) ^ 0x3;
int b0 = (x>>3) & 1;
int b1 = (x>>2) ^ 1;
int b2 = (x>>1) ^ 1;
return (!a) & ((!b0) | (b0&b1&b2));
}
conditional: 實現 x ? y : z
/*
* 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 = (x<<31)>>31;//把x擴充套件到31位
return (~x&y) | (x&z);
}
isLessOrEqualisLessOrEqual 返回a<=b
/*
* 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;
sy = (y>>31)&1;
z = x + ~y + 1; //x-y
s = ((z>>31) & 1) | (!(z^0)); //負數或者0
//x和y符號相同時看差的符號
//x<0 && y >=0 返回true
return ((!(sx^sy))&s) | (sx&(!sy));
}
logicalNeg: 返回一個數的邏輯值,0=flase,非0=true
/*
* 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;
x |= x>>8;
x |= x>>4;
x |= x>>2;
x |= x>>1;
x ^= 1;
return x&1;
}
howManyBits:返回用補碼錶示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,然後再+1
//如果是負數取反
int howManyBits(int x) {
int s,c1,c2,c3,c4,c5,c6;
int cnt = 0;
s = (x>>31)&1;
x = ((s<<31)>>31) ^ x;
s = !!(x>>16); //高16位是否非0
c1 = s<<4; //非0的話右移16位
x >>= c1;
s = !!(x>>8);
c2 = s<<3;
x >>= c2;
s = !!(x>>4);
c3 = s<<2;
x >>= c3;
s = !!(x>>2);
c4 = s<<1;
x >>= c4;
s = !!(x>>1);
c5 = s;
x >>= c5;
c6 = !!x;
cnt = c1+c2+c3+c4+c5+c6+1;
return cnt;
}
float
floatScale2: 返回2*f
/*
* 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
* 返回2*f
*/
unsigned floatScale2(unsigned uf) {
unsigned f = uf;
if ((f & 0x7F800000) == 0) //如果階碼為0時,尾數左移1位
f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);
else if ((f & 0x7F800000) != 0x7F800000) //階碼不等於128時,階碼+1
f =f + 0x00800000;
return f; //NaN
}
floatFloat2Int: float轉化成int
/*
* 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;
int e = (uf>>23) & 0xff;
int s = (uf>>31) & 1;
if (uf == 0) return 0;
uf <<= 8;
uf |= 1<<31;
uf >>= 8;
e -= 127;
if ((uf & 0x7f80000) == 0x7f80000 || e >= 32) return INF;
if (e < 0) return 0;
if (e <= 22) uf >>= 23-e;
else uf <<= e-23;
if (s) uf = ~uf + 1;
return uf;
}
floatPower2: 返回pow(2,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
*/
unsigned floatPower2(int x) {
unsigned INF = 0xff << 23;
int e = 127 + x;
if (x < 0) return 0;
if (e >= 255) return INF;
return e << 23;
}