2.61
A !(~x)
B !x
C !(~ (x | 0x00ffffff))
D !(~ (x | 0xffffff00))
2.65
分析:因為本題受12次操作的限制,故不能按位計算是否該位為1。考慮到本題隻需要判斷1的個數的奇偶性,而并不需要計算一共有多少個1。那麼我們考慮到如果能去掉偶數個1對結果并不會産生影響,這需要快速的去掉偶數個1。因為異或運算恰好可以把同為1時變成0。然後在利用分治的方法,整體異或來減少操作次數。
操作:1
1.前16和後16位對齊後異或,那麼這時候原來32位的奇偶性和目前異或出來的16位的結果一緻。
2.同理前8位和後8位對齊異或。
3.同理前4位和後4位對齊異或。
4.同理前2位和後2位對齊異或。
5.同理前1位和後1位對齊異或。
最後隻需要判斷最後那一位上是1還是0即可。
int even_ones(unsigned x)
{
unsigned y = x >> 16; x ^= y;
y = x >> 8; x ^= y;
y = x >> 4; x ^= y;
y = x >> 2; x ^= y;
y = x >> 1; x ^= y;
return !(x & 1);
}
2.73
【分析】首先判斷是否有無溢出,因為不能用判斷符号(<,>),是以我們可以考慮符号位,如果(x+y)的符号位和x與y的符号位都不同,則發生溢出。這個可以用兩次異或和一次與操作完成。
令ans= x+y
令ALL= (( x ^ ans) & (y ^ ans)) >> ( intBitCnt - 1);顯然當算術溢出時,ALL的32個位上的值均為1(111.....111),否則ALL= 0;Ps:因為是算術右移。
然後繼續判斷是正溢出還是負溢出,隻需要看x或者y的符号位即可判斷。
令x_sign= x >> (intBitCnt – 1); 如果正溢出則x_sign= 0 否則各個數位上的值均為1(111....111)。
對于傳回的結果,ans| ALL 之後,如果溢出則結果為全1,否則結果仍為x+y。如果正溢出我們隻需要令其減去(1<<(intBitCnt – 1))即可,如果負溢出令其減去(1<<(intBitCnt-1)) ^ 111....111(全部1)即可,則否減去0。
這樣隻要上面參與運算的1與是否溢出,是否正負溢出有關就可以了。
ALL& 1 = 1 是溢出的判斷條件。
x_sign& ALL = 111.....111(全1)是負溢出的條件,0則可能正溢出,也可能不溢出。
int saturating_add(int x,int y)
{
int intBitCnt = sizeof(int) << 3;
int ans = x + y;
int ALL = (( x ^ ans) & (y ^ ans)) >> ( intBitCnt - 1);
int x_sign = x >> ( intBitCnt - 1);
return (ans | ALL) - ( (ALL & 1) << ( intBitCnt - 1))^ (x_sign & ALL);
}
2.76
AK = 5 【code】x<<2+x
Bk = 9 【code】x<<3+x
Ck = 30【code】x<<5-x<<1
Dk = -56 【code】x<<3- x << 6