在博客園潛水好久了,今天興致高昂的想寫一篇博客,寫的內容就是最近剛剛弄懂的關於位運算的題目。可能對那些老鳥老說這些是在基礎不過的東西了,但是我相信還是有很多的博客需要了解並掌握這個基礎的。
做題目前首先需要掌握的知識:
~ 取反運算符,如果運算位為1取反后則變為0,如果運算為為0取反后則為1
& 與運算符,當運算的兩個數同時為1時,則與運算的結果才為1,否則為0
| 或運算符,當運算的兩個數只要有一個1時,則或運算的結果為1,否則為0.
^ 異或運算符,當兩個運算位不同時為1,相同時是0
>> 右移運算符
<< 左移運算符
在內存中的運算都是以補碼的形式存在的。
正數的原碼、反碼、補碼相同。
負數的原碼:最高為符號為0代表正、1代表負。后面的數為整數轉換后的二進制數。
負數的反碼:除符號為以外的位進行取反,1變為0,0變為1
負數的補碼:負數的反碼+1
這里舉個簡單的負數的例子,這里以整數占4個字節為例:
整數-5
(-5)10 的原碼為:(10000000 00000000 00000000 00000101)2
(-5)10 的反碼為:(11111111 11111111 11111111 11111010)2
(-5)10 的補碼為:(11111111 11111111 11111111 11111011)2
算術右移:低位溢出,符號位不變,並用符號位補溢出的高位。
算術左右:符號位不變,低位補0
基礎知識就這么點了。不過這里沒有必要死記,在一邊做題目的時候,一邊在看定義,這樣對於理解會很有幫助的。
題目1
~2
因為:2為正數,所以2的原碼等於2的反碼等於2的補碼
因為計算中的運算都是以補碼的形式存在的。所以我們需要2的補碼為(00000000 00000000 00000000 00000010)2
對2的補碼進行取反運算得到: (11111111 11111111 11111111 11111101)2
此時得到的結論為(~2)的補碼為 (11111111 11111111 11111111 11111101)2
因為最高位為1,所以是負數看,負數的補碼等於負數的反碼+1
所以又可以得到了(~2)的反碼為 (11111111 11111111 11111111 11111100)2
根據反碼又可以得到(~2)的原碼為 (10000000 00000000 00000000 00000011)2
最后我們把二進制數轉化為十進制數-3.
所以~2=-3
題目2
2&3 2|3
因為2、3都為正數,所以2、3的原碼等於反碼等於補碼。
即(2)10的原碼、反碼、補碼為 (00000000 00000000 00000000 00000010)2
(3)10的原碼、反碼、補碼為 (00000000 00000000 00000000 00000011)2
緊接着我們開始與運算
00000000 00000000 00000000 00000010
& 00000000 00000000 00000000 00000011
00000000 00000000 00000000 00000010
在接着我們開始或運算
00000000 00000000 00000000 00000010
| 00000000 00000000 00000000 00000011
00000000 00000000 00000000 00000011
這與、或運算的結果為補碼,我們還需要進行轉化成原碼。
因為最高為0(符號位),所以表示整數。
即原碼等於反碼等於補碼。
所以2&3的原碼用二進制表示為 00000000 00000000 00000000 00000010
轉化成十進制為2
2|3的原碼用二進制表示為 00000000 00000000 00000000 00000011
轉化成十進制為3
題目3
13&7
同樣我們可以從題目中知道13、7都是正數,所以正數的原碼等於反碼等於補碼。
即(13)10的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00001101)2
(7)10的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00000111)2
最后我們在腦子里模擬在內存中的運算:
00000000 00000000 00000000 00001101
& 00000000 00000000 00000000 00000111
00000000 00000000 00000000 00000101
從結果中我們可以看出補碼的最高位符號位為0表示正數。
所以(13&7)10的原碼等於 (00000000 00000000 00000000 000000101)2
轉化成十進制數為5
題目4
5|4
同樣我們可以從題目中知道5、4都是正數,所以正數的原碼等於反碼等於補碼。
即(5)10的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00000101)2
(4)10的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00000100)2
最后我們在腦子里模擬在內存中的運算:
00000000 00000000 00000000 00000101
| 00000000 00000000 00000000 00000100
00000000 00000000 00000000 00000101
從結果中我們可以看出補碼的最高位符號位為0表示正數。
所以(5|4)10的原碼等於 (00000000 00000000 00000000 000000101)2
轉化成十進制數為5
整數相對而言還是相對簡單得,接着我們在來看幾個負數的題目。
題目5
(~-5)
首先我們可以知道-5是負數
所以我們要先轉化成原碼
(-5)10的原碼為 (10000000 00000000 00000000 00000101)2
在轉化成為反碼
(-5)10的反碼為 (11111111 11111111 11111111 11111010)2
在轉化成為補碼
(-5)10的補碼為 (11111111 11111111 11111111 11111011)2
得到了補碼我們可以開始取反運算了:
(~-5)10的補碼為 (00000000 00000000 00000000 00000100)2
這里可以看到最高為符號位為0,所以表示的是整數。
正數的原碼等於反碼等於補碼。
所以(~-5)10的原碼為 (00000000 00000000 00000000 00000100)2
最后(~-5)=4
緊接着我們來看左移運算符和右移運算符。
題目6
-1>>2
因為是-1是負數,所有我們先通過一系列的轉化得到他的補碼。
(-1)10 的原碼為: (10000000 00000000 00000000 00000001)2
(-1)10 的反碼為: (11111111 11111111 11111111 11111110)2
(-1)10 的補碼為: (11111111 11111111 11111111 11111111)2
緊接着我們開始右移運算,溢出位用符號位來補。右移2位得到
(-1>>2)10 的補碼為: (11111111 11111111 11111111 11111111)2
因為符號位為1,所以是負數,我們接着算出反碼,原碼。
(-1>>2)10 的反碼為: (11111111 11111111 11111111 11111110)2
(-1>>2)10 的原碼為: (10000000 00000000 00000000 00000001)2
所有-1>>2=-1
-1<<2
我直接用上面的到的
(-1)10 的補碼為: (11111111 11111111 11111111 11111111)2
緊接着我們在對他進行左移,低位用0補。左移兩位得到的結果是
(-1<<2)10 的補碼為: (11111111 11111111 11111111 11111100)2
因為符號位為1,所以是負數,我們接着算出反碼,原碼。
(-1<<2)10 的反碼為: (11111111 11111111 11111111 11111011)2
(-1>>2)10 的原碼為: (10000000 00000000 00000000 00000100)2
所有-1<<2=-4
題目7
1>>2
因為1是正數,所有原碼等於反碼等於補碼,即
(1)10 的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00000001)2
緊接着我們開始右移運算,
(1>>2)10 的補碼為 (00000000 00000000 00000000 00000000)2
因為符號位為0,所有原碼等於反碼等於
補碼為 (00000000 00000000 00000000 00000000)2
所有1>>2=0
1<<2
因為1是正數,所有原碼等於反碼等於補碼,即
(1)10 的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00000001)2
緊接着我們開始右移運算,
(1>>2)10 的補碼為 (00000000 00000000 00000000 00000100)2
因為符號位為0,所有原碼等於反碼等於
補碼為 (00000000 00000000 00000000 00000100)2
所有1<<2=4
題目8
-3^3
首先-3的為負數,所以
(-3)10 的原碼為 (10000000 00000000 00000000 00000011)2
(-3)10 的反碼為 (11111111 11111111 11111111 11111100)2
(-3)10 的原碼為 (11111111 11111111 11111111 11111101)2
在因為3為正數則
(3)10 的原碼等於反碼等於補碼為 (00000000 00000000 00000000 00000011)2
緊接着我們開始異或運算
11111111 11111111 11111111 11111101
^ 00000000 00000000 00000000 00000011
11111111 11111111 11111111 11111110
(-3^3) 10 的補碼為 (11111111 11111111 11111111 11111110)2
因為符號位為1,所有是負數,所有
(-3^3) 10 的反碼為 (11111111 11111111 11111111 11111101)2
(-3^3) 10 的原碼為 (10000000 00000000 00000000 00000010)2
所有(-3^3)=-2
題目暫時就先這么多,因為我們要學會舉一反三的思想。當然上面只不過是我們的理論知識,但是我們程序員需要有一種用代碼檢驗真理的思想,我這里檢驗的代碼用的是php,因為他的整型都是有符號的。
下面附上php代碼
/*運行環境Win7 64位旗艦版 *服務器IIS7.5 *代碼語言PHP *編寫日期2012-5-31 *編寫人:JimmyWu * */ <html> <head> <title>位運算練習</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> </head> <body> <?php echo '整形的長度'.PHP_INT_SIZE.'<br />'; //位運算 echo '~2='.(~2).'<br />'; echo '2&3='.(2&3).'<br />'; echo '2|3='.(2|3).'<br />'; echo '~-5='.(~-5).'<br />'; echo '13&7='.(13&7).'<br />'; echo '5|4='.(5|4).'<br />'; echo '-3^3='.(-3^3).'<br />'; echo '-1>>2 = '.(-1>>2).'<br />'; echo '1>>2 = '.(1>>2).'<br />'; echo '-1<<2 = '.(-1<<2).'<br />'; echo '1<<2 = '.(1<<2).'<br />'; ?> </body> </html>
如果不對請指出並給我留言。最后歡迎關注我,也歡迎技術上的交流。