CSAPP LAB1 DataLab
用限定的運算符與結構實現一些功能,主要考察對位運算的瞭解,基本數據類型,浮點數,以及智商。
參考大佬1
參考大佬2
那個不用if的絕對值挺好的,據說可以加速絕對值計算,但是我測試並沒有快多少>_<
int abs(int x)
{
int res=x>>31;
res=(x+res)^res;
return res;
}
有一些太複雜了不想想了,就直接抄大佬了。用的時候再補吧~
/*
* CS:APP Data Lab
*
* <Please put your name and userid here>
* Id:P.H.S
* 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
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
int getByte(int x, int n) {
//移n沒結果時要考慮移x
int tmp=(x>>(n<<3));
return tmp&0xff;
}
/*
* 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) {
int k=~(1<<31);
int t;
k=((k>>n)<<1)|1;//左移n-1位,n爲0就右移一位
t=k&(x>>n);
return t;
}
/*
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
int bitCount(int x) {
/*抄的,完全沒思路*/
int count;
int tmpMask1 = (0x55)|(0x55<<8);
int mask1 = (tmpMask1)|(tmpMask1<<16);
int tmpMask2 = (0x33)|(0x33<<8);
int mask2 = (tmpMask2)|(tmpMask2<<16);
int tmpMask3 = (0x0f)|(0x0f<<8);
int mask3 = (tmpMask3)|(tmpMask3<<16);
int mask4 = (0xff)|(0xff<<16);
int mask5 = (0xff)|(0xff<<8);
count = (x&mask1)+((x>>1)&mask1);
count = (count&mask2)+((count>>2)&mask2);
count = (count + (count >> 4)) & mask3;
count = (count + (count >> 8)) & mask4;
count = (count + (count >> 16)) & mask5;
return count;
/*抄網上的,我個人習慣lowbit寫法,需要用while
while(x)
{
x-=(x&(-x));
k++;
}
*/
}
/*
* bang - Compute !x without using !
* Examples: bang(3) = 0, bang(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int bang(int x) {
int t=(~x)+1;//只有0x00000000和0x80000000按位取反+1等於本身,xor後等於0
int k=(x>>31)&1;//區分0x00000000和0x80000000
return 1^((((t^x)>>31)&1)|k);
}
/*
* tmin - return minimum two's complement integer
* 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) {//沒懂題
n=32+(~n)+1;
return !(x^((x<<n)>>n));
/*先左移32-n位,在右移32-n位,即保留最後n位數。在與x異或
若兩者相同表示x可被表示爲一個n位整數,!0爲1
*/
}
/*
* 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) {//補碼右移本質是向負無窮取整
int m=x>>31;//x正數0x00000000,x負數0xffffffff
int k=(1<<n)+(~0);//(2^n)-1
x=x+(m&k);
return x>>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) {
return !((x>>31)|(!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 s1=(x>>31)&1;
int s2=(y>>31)&1;
int valid=s1^s2;
int res=y+(~x)+1;
return (((!(res>>31))&1)&(!valid))|(valid&(s1)&(!s2));
}
/*
* 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 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)));
//for non zero bitsNumber, it should add 0
//for zero bitsNumber, it should subtract 1
bitsNumber=bitsNumber+(!!bitsNumber)+(~0)+(!(1^x));
//當x爲0時,還需要減一才能得到正確值。
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 tmp=uf&(0x7fffffff);
unsigned res=uf^(0x80000000);
if(tmp>(0x7f800000)) res= uf;
return res;
}
/*
* float_i2f - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* 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.
* 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) //指數是0,特殊小數
{
//左移一位
f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);
}
else if ((f & 0x7F800000) != 0x7F800000)//一般浮點數,直接加階碼
{
f =f + 0x00800000;
}
return f;//剩下NAN
}