c c 位操作的趣味應用

2021-09-06 08:30:20 字數 3796 閱讀 9069

(**部分,略作刪減;加下劃線部分,是後加內容,非原文內容)

位操作有很有趣的應用,下面列舉出一些,歡迎讀者補充。

1. 高低位交換

給出乙個16位的無符號整數。稱這個二進位制數的前8位為「高位」,後8位為「低位」。現在寫一程式將它的高低位交換。例如,數34520用二進位制表示為:

10000110 11011000

將它的高低位進行交換,我們得到了乙個新的二進位制數:

11011000 10000110

它即是十進位制的55430。

這個問題用位操作解決起來非常方便,設x=34520=10000110 11011000(二進位制) 由於x為無符號數,右移時會執行邏輯右移即高位補0,因此x右移8位將得到00000000 10000110。而x左移8位將得到11011000 00000000。可以發現只要將x>>8與x<<8這兩個數相或就可以得到11011000 10000110。用**實現非常簡潔:

a = (a >> 8) | (a << 8

);

2. 二進位制逆序我們知道如何對字串求逆序,現在要求計算二進位制的逆序,如數34520用二進位制表示為:

10000110 11011000

將它逆序,我們得到了乙個新的二進位制數:

00011011 01100001

它即是十進位制的7009。

回顧下字串的逆序,可以從字串的首尾開始,依次交換兩端的資料。在二進位制逆序我們也可以用這種方法,但運用位操作的高低位交換來處理二進位制逆序將會得到更簡潔的方法。類似於歸併排序的分組處理,可以通過下面4步得到16位資料的二進位制逆序(我覺得如果將這4步倒過來執行,可以得到相同的結果,並且更容易理解。):

第一步:每2位為一組,組內高低位交換

1000

0110

1101

1000

-->010

0100

1111

0010

0第二步:每4位為一組,組內高低位交換

010010

0111

1001

00-->00

0101

1010

1100

01第三步:每8位為一組,組內高低位交換

0001

0110

1011

0001

-->0110

0001

0001

1011

第四步:每16位為一組,組內高低位交換

01100001

00011011

-->00011011

01100001

對第一步,可以依次取出每2位作一組,再組內高低位交換,這樣有點麻煩,下面介紹一種非常有技巧的方法。先分別取10000110 11011000的奇數字和偶數字,空位以下劃線表示。

原 數   100

0011

0110

1100

0 奇數字 1_0_0_1_ 1_0_1_0_

偶數字 _0_0_1_0 _1_1_0_0

將下劃線用0填充,可得

原 數   100

0011

0110

1100

0 奇數字 10000010 10001000

偶數字 00000100 01010000

再將奇數字右移一位,偶數字左移一位,此時將這兩個資料相或(原文為相與,應該是作者筆誤

)即可以達到奇偶位上資料交換的效果了。

原 數          10000110 11011000

奇數字右移   0

1000011 01101100

偶數字左移   0000100 010100000

相或得到      01001000 11100100

可以看出,結果完全達到了奇偶位的資料交換,再來考慮**的實現——

取x的奇數字並將偶數字用0填充用**實現就是x & 0xaaaa

取x的偶數字並將奇數字用0填充用**實現就是x & 0x5555

因此,第一步就用**實現就是:

x = ((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1);

類似可以得到後三步的**。完整程式如下:

#include 

template

void

printfbinary(t a)

putchar('\n

');}int

main()

執行結果如下:

3. 二進位制中1的個數

統計二進位制中1的個數可以直接移位再判斷,當然像《程式設計之美》書中用迴圈移位計數或先打乙個表再計算都可以。本文詳細講解一種高效的方法。以34520為例,可以通過下面四步來計算其二進位制中1的個數。

第一步:每2位為一組,組內高低位相加 1

0000

1101

1011

000

-->01 00 01 01  10 01 01 00

第二步:每4位為一組,組內高低位相加

010001

0110

010100

-->0001 0010 0011 0001 (以第2組為例,01 + 01 = 10)

第三步:每8位為一組,組內高低位相加

0001

0010

0011

0001

-->00000011 00000100

第四步:每16位為一組,組內高低位相加

00000011

00000100

-->00000000 00000111

這樣最後得到的00000000 00000111即7即34520二進位制中1的個數。類似上文中對二進位制逆序的做法不難實現第一步的**:

x = ((x & 0xaaaa) >> 1) + (x & 0x5555);

好的,有了第一步,後面幾步就請讀者完成下吧,先動動筆再看下面的完整**:

#include 

template

void

printfbinary(t a)

putchar('\n

');}int

main()

執行結果如下:

可以發現巧妙運用分組處理確實是解決很多二進位制問題的靈丹妙藥。

4. 缺失的數字

由於有乙個數字消失了,那必定有乙個數隻出現一次而且其它數字都出現了偶數次。用搜尋來做就沒必要了,利用異或運算的兩個特性:

1.自己與自己異或結果為0

2.異或滿足交換律。

因此我們將這些數字全異或一遍,結果就一定是那個僅出現乙個的那個數。 示例**如下:

#include 

intmain()

;

int lostnum = 0

;

for (int i = 0; i < maxn; i++)

lostnum ^=a[i];

printf(

"缺失的數字為: %d\n

", lostnum);

return0;

}

位操作是一種高效優美的方法,同時由於其高效的運算效能和掌握難度較大,位操作運算一直是筆試面試時的熱門話題之一。

c c 的位操作

c c 的位操作 說明,本文章面向初學者,高手勿看,如有問題需要 請發郵件 xjtufjj stu.xjtu.edu.cn c c 是一種系統程式語言,之所以這樣說其中乙個原因是是因為其提供的位操作的能力。其提供的位操作符直接對應於相關的彙編指令。在現實的程式設計實踐中,合理的使用位操作會大大提高效...

C C 位操作 位運算

在c語言中,可以單獨操控變數的位 bit 一般高階語言不會處理這級別的細節,c在提供高階語言便利的同時,還能為組合語言所保留的級別上工作,這使其成為編寫裝置驅動程式和嵌入式 的首選語言。目錄 二進位制整數 binary 有符號整數 八進位制 octal 十六進製制 hex 位運算子 按位與 的用途 ...

c c 中的位操作

c c 支援比較低階的位運算,在是眾人皆知的了。每本c c 的教科書都會說到這部分的內容,不過都很簡略,我想會有很多人不知道位運算用在什麼地方。這個帖子就簡略說說位運算的用處,更進一步的用法要大家自己去體會。而主要說的是操作標誌值方面。define bti msk bit 1 bit define ...