這可能是CDSN最良心的CSAP_label1了
學生狗,在學CSAP,做完label1肝得要吐血(滑稽.jpg)
之前上網發現CDSN好像還沒解釋的很詳細的label1
自己就把實驗報告貼出來吧
- 由於離ddl還差幾天(滑稽.jpg)
- 柴雲鵬老師的學生,你們是我的同班同學歐
烏拉!
先貼原始碼`/*
- CS:APP Data Lab
- 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.
*/
#if 0
/*
- Instructions to Students:
- STEP 1: Read the following instructions carefully.
*/
You will provide your solution to the Data Lab by
editing the collection of functions in this source file.
INTEGER CODING RULES:
Replace the “return” statement in each function with one
or more lines of C code that implements the function. Your code
must conform to the following style:
int Funct(arg1, arg2, …) {
/* brief description of how your implementation works */
int var1 = Expr1;
…
int varM = ExprM;
varJ = ExprJ;
...
varN = ExprN;
return ExprR;
}
Each “Expr” is an expression using ONLY the following:
- Integer constants 0 through 255 (0xFF), inclusive. You are
not allowed to use big constants such as 0xffffffff. - Function arguments and local variables (no global variables).
- Unary integer operations ! ~
- Binary integer operations & ^ | + << >>
Some of the problems restrict the set of allowed operators even further.
Each “Expr” may consist of multiple operators. You are not restricted to
one operator per line.
You are expressly forbidden to:
- Use any control constructs such as if, do, while, for, switch, etc.
- Define or use any macros.
- Define any additional functions in this file.
- Call any functions.
- Use any other operations, such as &&, ||, -, or ?:
- Use any form of casting.
- Use any data type other than int. This implies that you
cannot use arrays, structs, or unions.
You may assume that your machine:
- Uses 2s complement, 32-bit representations of integers.
- Performs right shifts arithmetically.
- Has unpredictable behavior when shifting an integer by more
than the word size.
EXAMPLES OF ACCEPTABLE CODING STYLE:
/*
- 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;
}
/*
- 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;
}
FLOATING POINT CODING RULES
For the problems that require you to implent floating-point operations,
the coding rules are less strict. You are allowed to use looping and
conditional control. You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants.
You are expressly forbidden to:
- Define or use any macros.
- Define any additional functions in this file.
- Call any functions.
- Use any form of casting.
- Use any data type other than int or unsigned. This means that you
cannot use arrays, structs, or unions. - Use any floating point data types, operations, or constants.
NOTES:
- Use the dlc (data lab checker) compiler (described in the handout) to
check the legality of your solutions. - Each function has a maximum number of operators (! ~ & ^ | + << >>)
that you are allowed to use for your implementation of the function.
The max operator count is checked by dlc. Note that ‘=’ is not
counted; you may use as many of these as you want without penalty. - Use the btest test harness to check your functions for correctness.
- Use the BDD checker to formally verify your functions
- The maximum number of ops for each function is given in the
header comment for each function. If there are any inconsistencies
between the maximum ops in the writeup and in this file, consider
this file the authoritative source.
/*
- STEP 2: Modify the following functions according the coding rules.
- IMPORTANT. TO AVOID GRADING SURPRISES:
-
- Use the dlc compiler to check that your solutions conform
-
to the coding rules.
-
- Use the BDD checker to formally verify that your solutions produce
-
the correct answers.
*/
#endif
/* Copyright © 1991-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
http://www.gnu.org/licenses/. /
/ This header is separate from features.h so that the compiler can
include it implicitly at the start of every compilation. It must
not itself include <features.h> or any other header that includes
<features.h> because the implicit include comes before any feature
test macros that may be defined in a source file before it first
explicitly includes a system header. GCC knows the name of this
header in order to preinclude it. /
/ We do support the IEC 559 math functionality, real and complex. /
/ wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
Unicode 6.0. /
/ We do not support C11 <threads.h>. /
//Rating:1
/
- 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)) ;
}
/ - evenBits - return word with all even-numbered bits set to 1
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 8
- Rating: 1
/
int evenBits(void) {
int x = 85 ;
int y = (x<<8) ;
x = x|y ;
y = (x<<16) ;
x = x|y ;
//printf("%x",x) ;
return x;
}
/ - fitsShort - return 1 if x can be represented as a
- 16-bit, two’s complement integer.
- Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 8
- Rating: 1
*/
int fitsShort(int x) {
int y = x >> 15;
return !( (y >> 16) ^ y);
//int a = (x>>15)<<16 ;
//printf("%x\n",a) ;
//現在的思路已知了如果a = ffff0000 ;或者a = 0 ;
//那麼這個就可以b表示
//關鍵問題處在輸出上
//如何用兩個操作符聰明的輸出?
//return !(a>>16+1)
}
/*
-
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) {
/int a ;
a = 1 ;
a = a<<31 ;//現在a是min
//printf("%d\n",a) ;
return !(a+x+1) ;/
int y=(x+1);
return (!(y+y))^(!~x);
}
/ -
minusOne - return a value of -1
-
Legal ops: ! ~ & ^ | + << >>
-
Max ops: 2
-
Rating: 1
/
int minusOne(void) {
return ~0 ;
}
/ -
upperBits - pads n upper bits with 1’s
-
You may assume 0 <= n <= 32
-
Example: upperBits(4) = 0xF0000000
-
Legal ops: ! ~ & ^ | + << >>
-
Max ops: 10
-
Rating: 1
*/
int upperBits(int n) {return ((!!n)<<31)>>(n+(~0)) ;
//return (0&(!n+(0)))<<(32+(~n+1)) ;
/*int a ;
a = ~0 ;
//printf("%x\n",a) ;
int b ;
b = ~n+1 ;//b = -n ;
// printf("%d",b) ;
b = 32 + b ;
return ((a>>b)<<b) ; /
}
//Rating:2
/ -
allEvenBits - return 1 if all even-numbered bits in word set to 1
-
Examples allEvenBits(0xFFFFFFFE) = 0, allEvenBits(0x55555555) = 1
-
Legal ops: ! ~ & ^ | + << >>
-
Max ops: 12
-
Rating: 2
*/
int allEvenBits(int x) {
int y ;
y = 0xAA ;
y = y|y<<8 ;
y = y|y<<16 ;
return !~(x|y) ;
}
/*
- byteSwap - swaps the nth byte and the mth byte
- Examples: byteSwap(0x12345678, 1, 3) = 0x56341278
-
byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD
- You may assume that 0 <= n <= 3, 0 <= m <= 3
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 25
- Rating: 2
/
int byteSwap(int x, int n, int m) {//sladk;lskdlaskdl;askdlaskdlaskdlskalfkjsakljfklasjfaksjf;lasjlfaksfl;askf;las
//unsigned int a = x ;
int nn = n << 3;
int mm = m << 3;
int p = ( ( x >> mm ) ^ ( x >> nn) ) & 0xFF;
return x ^ ( ( p << mm) | ( p << nn) );
}
/ - copyLSB - set all bits of result to least significant bit of x
- Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 5
- Rating: 2
/
int copyLSB(int x) {
return ((x<<31)>>31) ;
}
/ - 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 y = (x>>31) ;
x += y&((1<<n)+~0) ;
x=x>>n ;
return x ;
/*int y = (x>>31) ;
//得到原碼
x = (x+y)^y ;
x = x>>n ;
//printf("%d ",x) ;
//printf("%d ",y) ;
x = (x^y) + (1&y) ;
return x ;*/
}
/*
- leastBitPos - return a mask that marks the position of the
-
least significant 1 bit. If x == 0, return 0
- Example: leastBitPos(96) = 0x20
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 6
- Rating: 2
/
int leastBitPos(int x) {
return (~x+1)&x ;
}
/ - oddBits - return word with all odd-numbered bits set to 1
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 8
- Rating: 2
/
int oddBits(void) {
int x = 170 ;
x = x|(x<<8) ;
x = x|(x<<16) ;
//printf("%x",x) ;
return x;
}
//Rating:3
/ - bitMask - Generate a mask consisting of all 1’s
- lowbit and highbit
- Examples: bitMask(5,3) = 0x38
- Assume 0 <= lowbit <= 31, and 0 <= highbit <= 31
- If lowbit > highbit, then mask should be all 0’s
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 16
- Rating: 3
*/
int bitMask(int highbit, int lowbit) {//zxclzkxlc;zk;xlckzx;lkcl;zxkc;lzxkcl;zxkcl;zxkcl;zxkcl;zxkcl;zxkcz
int i=~0;
return (((i << highbit) << 1) ^ (i << lowbit)) & (i << lowbit);
/*int x = ~0 ;
//set low boundry ;
int y = (x<<lowbit) ;
//printf("%x\n",y) ;
//set height boundry ;
unsigned z = x ;
int cc = (~highbit)+32 ;
z = (z>>cc) ;
// printf("%x\n",z) ;
return y&z ;*/
}
/*
- isLess - if x < y then return 1, else return 0
- Example: isLess(4,5) = 1.
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 24
- Rating: 3
*/
int isLess(int x, int y) {
int z=~y;
return (((x+z+1)&(x^z)|(x&z))>>31)&0x1;
/*int y1 = ((y>>31)<<31) ;
//printf("%x\n",y1) ;
int y2 = ~y1 ;
//printf("%x\n",y2) ;
y = y^y2 ;
y +=1 ;
y += y1 ;
//printf("%d\n",y) ;
int z = x+y ;
unsigned z1 = z ;
return (z1>>31) ;*/
}
/*
- 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>>n ;
// int y = (x<<1) ;
//printf("%x\n",y1) ;
//rintf("%x\n",(x<<n)) ;
int y1 = (((x>>31)<<31)>>(n))<<1 ;
return (x>>(n))^y1 ;
}
/*
- satMul2 - multiplies by 2, saturating to Tmin or Tmax if overflow
- Examples: satMul2(0x30000000) = 0x60000000
-
satMul2(0x40000000) = 0x7FFFFFFF (saturate to TMax)
-
satMul2(0x80000000) = 0x80000000 (saturate to TMin)
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 20
- Rating: 3
/
int satMul2(int x) {
int a=x<<1;
int b=a>>31;
int c=(x^a)>>31;
int tmin=1<<31;
return ((~c)&a)+(c&(b+tmin)) ;
}
/ - subOK - Determine if can compute x-y without overflow
- Example: subOK(0x80000000,0x80000000) = 1,
-
subOK(0x80000000,0x70000000) = 0,
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 20
- Rating: 3
*/
int subOK(int x, int y) {
int z ;
int m = y ;
y = (~y)+1 ;
z = x+y ;
//printf("%x\n",z) ;
z = (zx)&(mx) ;
//printf("%x\n",z) ;
//unsigned k = z ;
//printf("%x\n",!(k>>31)) ;
return !((z>>31)&1) ;
}
//Rating:4
/*
- bang - Compute !x without using !
- Examples: bang(3) = 0, bang(0) = 1
- Legal ops: ~ & ^ | + << >>
- Max ops: 12
- Rating: 4
/
int bang(int x) {
int y = ((x)&((x+(0)))) ;
return (y>>31)&1 ;
}
/ - bitParity - returns 1 if x contains an odd number of 0’s
- Examples: bitParity(5) = 0, bitParity(7) = 1
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 20
- Rating: 4
/
int bitParity(int x) {
x = x^(x>>16) ;
x = x^(x>>8) ;
x = x^(x>>4) ;
x = x^(x>>2) ;
x = x^(x>>1) ;
//unsigned k = x ;
return x&1 ;
}
/ - isPower2 - returns 1 if x is a power of 2, and 0 otherwise
- Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
- Note that no negative number is a power of 2.
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 20
- Rating: 4
/
int isPower2(int x) {
return !(((x&(~x+1))^x)|(!x)|(x>>31));
}
//Extra
/ - 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) {
return 2;
}
/ - leftBitCount - returns count of number of consective 1’s in
-
left-hand (most significant) end of word.
- Examples: leftBitCount(-1) = 32, leftBitCount(0xFFF0F0F0) = 12
- Legal ops: ! ~ & ^ | + << >>
- Max ops: 50
- Rating: 4
*/
int leftBitCount(int x) {
return 2;
}`
之後是我寫實驗報告:所有程式都跑過了,經得起測試
第一題:bitAnd
如果使用&操作,那麼1&1 = 1 ;
其他的情況都是零
但是如果使用或操作,那麼0|0 = 0
其他的三種情況都是1
我們先用~把傳入的兩個數字取反
則之前的 1變成了0
再將兩個數|一下
只有之前兩個數全是一個二進位制位再操作之後表現為0
其餘二進位制位表現為1
通過對新得到的二進位制串取反操作得到正確結果
程式碼為: return ((x)|(~y)) ;
第二題 :eventbit
這裡的要求是偶數位都是1
已知
1.二進位制串的計數是從零開始
2.只能夠使用255之內的整數
先構建出01010101的八位(十進位制是85)
之後右移八位,並|自身
再右移16位|上一步的結果
的到來所要求的函式值
程式碼為
:int x = 85 ;
int y = (x<<8) ;
x = x|y ;
y = (x<<16) ;
x = x|y ;
//printf("%x",x) ;
return x;
第三題:fitsShort
題目要求判斷這個三十二位的二進位制數是否能夠用十六位的二進位制數表示出來
首先明確:
三十二位的二進位制數是有1個符號位和三十一個有效位
十六位的二進位制數是有1個符號位和十五個二進位制位
那麼問題就變成了:
如何將三十一位壓縮成十五位
對於正數而言:這代表著31到十六位都是0
對於負數而言:這代表著31到十六位都是一(這樣負數才足夠大 ,大到能夠表示)
先將x>>15
將所有的有效位去掉
如果能夠壓縮,剩下的數字應該出來符號位之外不包含任何資訊
負數
0xffff(不確定)【全是 1的時候可以表示】
正數(和0)
0x0000(不確定)【全是0的時候可以表示】
利用整數右移的技巧
如果可以表示,則(x>>15)>>16 = x>>15
其他情況不能表示
利用異或判斷相等關係
程式碼為
int y = x >> 15;
return !( (y >> 16) ^ y);
第四題:ismax
題目要求判斷一個數是否是最大值
三十二位機的十六進位制表示式是0x7fffffff
如果這max+1就會發生溢位,溢位成為最小的負數
0x80000000
由溢位的性質,又可得
0x80000000+0x8000000 = 0
基本完成
但如果傳入的是-1,也會得到相同的結果
所以我們要排除-1,這個操作就算成功了
由-1取反得0的性質可以排除-1
程式碼如下:
int y=(x+1);
return (!(y+y))^(!~x);
第五題:minusOne
本題目的是得到-1
由於-1不在0~255之內,所以不被允許直接宣告
先分析-1的二進位制串的形式
:11111111111111111111111111111111
不難發現,如果將-1取反,的得到的是0
0是可以直接被宣告的
程式碼:
Return ~0 ;
第六題: upperbits(int n)
題目要求:
將數字的前n個二進位制位設定為1
傳入0 的時候結果會是零
為了減少分類討論,我們要做到把零和非零的數並行操作
使用!!N
作為要操作的基準數
如果傳入的不是零 這個基準數變成了1
如果是零 ,則變成了 0 (怎麼操作結果都會為零)
先將!!N<<31
使得其位於最頂端
之後右移n-1位
由上題可知~0 = -1 ;
原始碼:
return ((!!n)<<31)>>(n+(~0)) ;
第七題:allEvenBits(int x)
題目要求:要判斷是否所有的偶數位全是1
利用^操作符
先令y = 0x(AA)(也就是10101010)
就像第二題那樣將將這個八位的特徵擴充套件到三十位
y = y|y<<8 ;
y = y|y<<16 ;
通過^進行比較
原始碼:
y = 0xAA ;
y = y|y<<8 ;
y = y|y<<16 ;
return !~(x|y) ;
第八題:bitswap(int x ,int n ,int m)
題目要求:將第m和第n個位元組交換
首先:將m,和n分別擴充套件到原來的 八倍,代表一個個位元的順序
其次
將該數字的第m個位元組移動到最低有效位ing機率
對第n個位元組進行同樣操作
這兩者異或,最低八位就m^n(指的是位元組的內容)
利用異或的性質發現規律:
Mnm = n ;
Mnn = m ;
並0^a = a
則
先將m^n的前二十四位清除
再將m^n移動到第m個位元組,與之進行異或
同理對於第n個位元組進行操作
原始碼:
int nn = n << 3;
int mm = m << 3;
int p = ( ( x >> mm ) ^ ( x >> nn) ) & 0xFF;
return x ^ ( ( p << mm) | ( p << nn) );
第九題:copyLSB(int x)
題目要求:將這個整數的所有二進位制位都置為最低的哪那一位
可以利用整數右移的格式:
如果第一位是1,那麼右移之後左邊全部補1
則要先將最低為的那個數值放到最高位
在這個過程中其他資料全部被清洗掉了
並且右邊三十一位全部是1
之後利用整數右移的格式右移三十一位
原始碼:
return ((x<<31)>>31) ;
第十題:divpwr2(int x, int n)
題目要求:
求得x/2^n
並且向0取整
難點分析
如果暴力直接右移
如果正數是向0取整
如果x是負數切不被整除
負數後三十一位的某項會被捨棄
但是負數後三十一位某一位有值代表的意義是一個正數
這會導致直接暴力右移對於負數而言是向-∞取整
解題思路
通過上面的分析,可以得到難點是負數上
我們可以通過對於負數+2^n-1的方式得到解決
這樣只要負數(二進位制)的後n位不全是零,那麼就可以通過進位向0取整
下一個問題是:正數和負數要並行運算
我們可以通過擴大符號影響的方式來實現
N = x>>31
如果是正數這是0
0&任何數是0
對於負數這是-1
-1&任何數是任何數本身
經過分析發現,可以通過運用N的方式使得負數增加一個數在處理,而正數直接處理
原始碼:
int y = (x>>31) ;
x += y&((1<<n)+~0) ;
x=x>>n ;
return x ;
第十一題:leastBitPos(int x)
題目要求:
返回一個面具,這個面具從右往左數第一個1的位置和傳進來的x的第一個1的位置相等,並且其他位置全是零
如果x是零,那麼這個面具也就是0
解題思路:
從右往左數第一個1的性質就是其右邊全是零,並且這個位置是1
這個特殊的性質很難判斷
我們不妨取反
那就變成了
這個位置自己是0
這個位置的右邊所有位置都是1
這樣+1之後這個位置變成1,這個位置右邊變成0成為了這狀態的特有性質
我們發現,只有這個位置在取反加一之後和之前都是1
則可以返回(~x+1)&x
原始碼:
return (~x+1)&x ;
第十二題:oddBits(void)
題目要求
要求返回一個使奇數位置全為1,其他位置全為0的數字
思路:
和第二題一樣的傻瓜方法
先宣告一個數字滿足這種性質
之後做兩次左移+|操作
程式碼:
int x = 170 ;
x = x|(x<<8) ;
x = x|(x<<16) ;
//printf("%x",x) ;
return x;
第十三題:bitMask(int highbit, int lowbit)
題目要求:
獲得一個面具
這個面具在最高位和最低位之間為1
其餘的地方為0
Low>height的時候為0
總體思路:
獲得大斷1的方式有兩種
首先是先將1移動到最高位之火再右移
其次是先通過~0獲得一個0xffffffff之後進行左移
當然第一種方式也能偶完成這個函式要完成的工作,我們不妨先選擇我比較習慣的第二種方式
首先得到一個0xfffff記為a
之後將a左移low位得到b
再將a左移height+1位得到c
對於b和c而言
只有在low和hight中間區域(包括兩個數本身)的區域是不一致的
我們簡單的做一個異或操作
可以得到自己的面具
另一個問題:
如果這樣操作,low>height的時候這個面具不是0
解決方案:
我可以且上一個a<<low
這樣有效的在low過大的時候把面具中所有的1都清楚掉
原始碼:
int i=~0;
return (((i << highbit) << 1) ^ (i << lowbit)) & (i << lowbit);
第十四題:isLess(int x, int y)
題目要求:
判斷x<y是否成立
思路:
X<y一般會有三種情況
X < 0 ,Y<0 X-y>0
X>0, Y>0 x-y<0 ;
X<0 ,Y>0
因為會有減法出現,先將y取反
Z = ~y ;
可以得到一個顯而易見的結果:
(x&z) 得最高位= 1 ; x = z =1的時候
或者(x+z+1 ^ x得最高位為1 x!=z的時候
則表示式為
return (((x+z+1)&(x^z)|(x&z))>>31)&0x1;
原始碼為:
int z=~y;
return (((x+z+1)&(x^z)|(x&z))>>31)&0x1;
第十五題:logicalShift(int x, int n)
題目要求:
實現邏輯右移:
思路:
面對的主要問題:
要對負數右移時候補足的1進行消除
同時由於要和正數進行並行操作
這部分的實現必須藉助正負數不同的部分(符號位)
先通過右移三十一位在左移三十一位的方式得到位於最左端的 符號位y
利用整形的規則將x>>n
之後將y>>n-1;
這裡要注意:如果n = 0 的時候會右移-1,也就是31位,這心啊然不是我們想要看到的
這一部分的操作可以優化(y>>n)<<1
並沒有增加操作符號的數量
此時
如果是負數,則y的前n位是1
如果是正數,則y的前n 位值0
而後面的都是0, 0^anything = anything
則可以聰明的通過異或
將負數的多餘的1消除
沒有影響正數
沒有對結果產生影響
原始碼:
int y1 = (((x>>31)<<31)>>(n))<<1 ;
return (x>>(n))^y1 ;
第十六題:int satMul2(int x)
題目其要求:
將一個數字乘二
如果溢位則取Tmax或者Tmin
解題思路:
什麼樣的數字*2之後會溢位?
顯然這個數字的第三十二位和第三十一位不相同的數字
解決了這個問題,我們面對的第二個問題就是:
如何讓溢位和不溢位的數字平行計算?
答案是通過問題一的特徵去處理著啦你各種情況:
如果這兩者不同
進行什麼操作
如果這兩者相同
進行什麼操作
在沒有分支語句的時候,最好的辦法就是預先計算出這兩個數字
通過& + 和 |操作在一種情況發生的時候將另一種情況設定為0
PS:面對分支的時候還有一種方案
就是把所有的情況用& 和|諒解
通過設定c& + ~c&
使得每個值在不同情況下或等於零或等於其他分支
不過那多用於分支的一種情況內部有不同的方式實現
或者我們要排除掉這個中間的幾個不成立的幾個特殊情況
我們要面對的第三個問題就是:
如何判斷溢位的應該是正無窮還是負無窮
這個問題的解決方案應該是通過提取原始資料符號位來進行並行操作的
三個主要的問題解決完了:
顯然可以得到
int a=x<<1;
//使得第一個問題中說的第二位移動到第一位上
int b=a>>31;
//將這個東西右三十一位
這裡用了一小技巧
因為溢位的時候,這個探討到底是一處到正無窮還是負無窮的量才派上用場
但是溢位的時候第二位和第一位恰好相反
這裡這個數字的提取而不是第一位的提取在後面為我們節省下了一個寶貴的操作符
int c=(x^a)>>31;
//比較第二位和第一位是否相等,並將其擴大到三十二位從而常委判斷標準(對應問題2)
int tmin=1<<31;
//得到一個tim的函式值
性質:tmin + 0xffffffff = tmax ;
這裡就用到了上述的小技巧:
正數溢位是得到最大的正數
得到最大的正數代表要 通過符號位得到一個tmin
但是正數的符號位是0所以只能夠得到一個0,
需要取反得到0xffffffff,
但是由於這個時候(已知溢位)
由問題1可知是在這個時候第一位和第二位是相反的
於是直接通過第二部的小trick來使得自己能夠生一個操作符
return ((~c)&a)+(c&(b+tmin)) ;
程式碼:
int a=x<<1;
int b=a>>31;
int c=(x^a)>>31;
int tmin=1<<31;
return ((~c)&a)+(c&(b+tmin)) ;
第十七題 : subOK(int x, int y)
題目要求:
判斷兩個函式相減是否會溢位
思路分析
第一個問題:
什麼樣的數相減會溢位:
X>0 ; y<0
X<0 , y>0
第二個問題:
如果這兩個數字溢位,會發生什麼
正 + 正 = 負
負 + 負 = 正
解決了這兩個問題
Z = x-y ;
(xy)&(xz)
31 &1
Return !
程式碼:
int z ;
int m = y ;
y = (~y)+1 ;
z = x+y ;
//printf("%x\n",z) ;
z = (zx)&(mx) ;
//printf("%x\n",z) ;
//unsigned k = z ;
//printf("%x\n",!(k>>31)) ;
return !((z>>31)&1) ;
第十八題:int bang(int x)
題目:
實現!的功能
同時不要使用!
這種一種情況存在不確定個1,另一種情況不存在1的問題
我們可以通過判斷是否進位的方式實現:(
如同之前的第十題:
除二,
向零取整)
判斷是否 要進位
分類討論:
最高層為就應該返回0
最高層不為1
加上0xffffff看是否會進位
程式碼:
int y = ((x)&((x+(0)))) ;
return (y>>31)&1 ;
第十九題目:bitParity(int x)
題意:
判斷這數中的1是奇數還是偶數
思路:將這個數字分兩半之後進行異或操作
異或操作完成之後再將結果(十六位)進行異或操作
得到結果
偶數數字會被消去
如果剩下1,代表有奇數個1
反之,是偶數個
第二十題: isPower2(int x)
題意:判斷這個數是不是二的倍數
思路:
先排除負數,再排除零
掙下的只有正數了
對於這些正數,想到之前寫的函式:
Least pos
那麼先通過(x&(~x+1))得到面具
符合本提要求的 函式值和麵具相等
return !(((x&(~x+1))^x)|(!x)|(x>>31));