最近在學習大牛Bryant O'Hallaron 的深刻理解計算機系統,發現學了這麼久的程序設計,其實有些基本的東西還不太瞭解,這不,這兩天在惡補整數,浮點數在計算機中的表示,而且開始作上面的習題,編程
由於剛開始,主要是作位運算方面的練習,這個之前沒怎麼重視,可是實在過重要了,搞不清楚位運算的別說本身編程很NB!學習
書里正好有這麼一道習題2.65,就是檢測一個無符號數的數位是否有偶數個1,並且要求不能超過12次基本運算!!那麼,我就根據位運算中異或的想法來實現,這個想法就是,偶數位的個數實際上就是這個無符號整數中設計
全部1的和,那麼對於32位的無符號整數,好比x1x2x3x4(xi=1字節),那麼 x1x2^x3x4其實就是他們高2字節和低2字節的1的和(mod2),這樣若是相同位上都有1的話,那麼異或得0,其實就是模去了一個偶數,而奇數是it
不會被模去的,結果是y1=x1x2^x3x4=y2,接下來再 y1^y2=z1,以此類推,直到最後剩下一位,若是這一位是0,則說明有偶數個2,不然就是奇數個2了,具體實現以下:io
1 #include<stdio.h>
2 #include<stdlib.h>
3 #define UINT_LEN 4
4
5 //由於使用了循環,實際計算次數略多,可是並不影響題目的本質,若是不用循環則知足要求,並且本代碼能夠適用到64位整數上,只要定義UNIT_LEN 5
6 int even_ones(unsigned x){
7 int u = 1<<UINT_LEN;
8 int p=UINT_LEN-1;
9 unsigned tx=x;
10 unsigned ty=x>>u;
11 printf("0: u=%d, tx=%x, ty=%x\n",u,tx,ty);
12 while(p>=-1){
13 tx = tx^ty;
14 u = u>>1;
15 ty = tx>>u;
16 printf("%d, u=%d, tx=%x, ty=%x\n",UINT_LEN-p,u,tx,ty);
17 p--;
18 }
19 int odd = tx&1;
20 return !odd;
21 }
22
23 int main(int argc,char** argv){
24 if(argc!=2){
25 perror("incorrect number of arguments!\n");
26 exit(1);
27 }
28
29 unsigned u=(unsigned) atoi(argv[1]);
30
31 even_ones(u)? printf("%d has even 1s!\n",u):printf("%d has odd 1s!\n",u);
32 return 0;
33 }
程序設計