被程序员忽视的位运算
在博客園潛水好久了,今天興致高昂的想寫一篇博客,寫的內容就是最近剛剛弄懂的關于位運算的題目。可能對那些老鳥老說這些是在基礎不過的東西了,但是我相信還是有很多的博客需要了解并掌握這個基礎的。
?
做題目前首先需要掌握的知識:
~?????????? 取反運算符,如果運算位為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><?phpecho '整形的長度'.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>
如果不對請指出并給我留言。最后歡迎關注我,也歡迎技術上的交流。
?
轉載于:https://www.cnblogs.com/Jimmy009/archive/2012/05/31/2528992.html
總結
以上是生活随笔為你收集整理的被程序员忽视的位运算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 批注
- 下一篇: fastreport 中 给数值形数据做