CS:APP datalab記錄

CS:APP這本書真的可以說是計算機的內容 給你從頭講到尾了,雖然每個領域方面的深度不夠,但是已經足夠了,因爲每一個領域都不是這麼簡單就能夠說完的,這本書能把這麼多東西講得很清楚真的不容易,所以看完建議挑戰一下lab。

 

要求:

不允許使用條件語句和循環語句,只允許使用8個運算符:! ˜ & ˆ | + >來完成,某些題目會額外限制運算符數量,最大隻能使用8位整數。

 

PART1

bitAnd

只能使用~和|運算符完成&運算,運算符最多隻能操作8次。

簡單,對兩個操作數分別取反再|就是他們兩個都沒有的位,然後再取反就是他們兩個都有的位了。

int bitAnd(int x, int y) {
    return ~((~x)|(~y));
}

 

getByte

獲得x的第n個字節,運算符最多操作6次,只能使用!~&^|+<<>>。

也很容易,首先很容易想到獲得x的第n個字節的方法是x>>(n*8)&0xff。但是不能用*號,所以改用<<運算符來代替*號。

int getByte(int x, int n) {
    return x>>(n<<3)&0xff;
}

 

logicalShift

實現邏輯右移,只能使用~&^|+<<>>運算符,最大操作數是20。

這題頗有難度,首先我們普通的>>運算是算數右移,在這基礎上把前n位清0就可以得到邏輯右移的結果,把前n位清0等於構造32-n位的1與之做&運算,構造這個可以用2**x - 1的方法,那麼2**x又等於2<<x,-1則等於0取反。但是構造32-n和無法使用long long類型讓我頭疼,結果我還是去看了別人怎麼寫這個。。。用左移再右移的方法防止溢出的同時可以利用符號位來讓前面填滿1。這是個好技巧。

int logicalShift(int x, int n) {
    return x>>n&(~(1<<31>>n<<1));
}

 

bitCount

計算整數裏有多少個位是1,只能使用~&^|+<<>>運算符,最大操作數40。

這題直接算的話是肯定超操作數的,那麼只能想辦法分塊然後同時操作了,我們把每8位分成一塊,塊裏面的每一位我們可以枚舉用&操作來判定,最後再把所有塊的結果加起來就完了。

int bitCount(int x) {
    int mask = ((1<<8|1)<<8|1)<<8|1;
    int sum = x&mask;
    sum += x>>1&mask;
    sum += x>>2&mask;
    sum += x>>3&mask;
    sum += x>>4&mask;
    sum += x>>5&mask;
    sum += x>>6&mask;
    sum += x>>7&mask;
    sum += sum>>8&0xff;
    sum += sum>>16&0xff;
    sum += sum>>24&0xff;
    return sum&0xff;
}

 

bang

做!運算,只能用~&^|+<<>>,最大操作數12。

這個首先得知道幾個技巧,假設x的最低位爲1的位置是i,x&(~x)+1可以得到結果只保留第i個1的數,即結果是2的i次方,而x|(~x)+1可以得到i及他以上的位置全部爲1的數,即得到...111111100000...(i個0,總位數-i個1)。而0是沒有1的,所以0做這兩個操作結果還是0。而其他數做上述的第二個操作得到的最高位必定是1,那麼我們就可以根據最高位來判定。

int bang(int x) {
    return ((x|((~x)+1))>>31)&1^1;
}

 

PART2

在這個部分可以使用條件和循環語句,可以使用int和unsigned類型的整數,不能使用union,struct,數組,不能使用浮點數,浮點數都以unsigned類型傳遞並返回。

tmin

返回補碼整數最小值。

int tmin(void) {
    return 1<<31;
}

 

fitsBits

判斷是否能用n位二進制表示一個數,可以返回1,否則返回0.

這題描述不太好,怎麼纔算能用n位來表示一個數呢,他的意思是前綴相同的話是可以用一位來省略的,比如前綴全是0就可以用一個...0來表示,全是1則用...1來表示,那麼問題就轉換爲去掉後綴n位後是否全是1或者全是0,具體思路看下面代碼。

int fitsBits(int x, int n) {
    int tmp = x>>(n+(~0));
    return !tmp|(!(tmp+1));
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章