被程序員忽視的位運算


  在博客園潛水好久了,今天興致高昂的想寫一篇博客,寫的內容就是最近剛剛弄懂的關於位運算的題目。可能對那些老鳥老說這些是在基礎不過的東西了,但是我相信還是有很多的博客需要了解並掌握這個基礎的。

 

做題目前首先需要掌握的知識:

~           取反運算符,如果運算位為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)

  最后我們在腦子里模擬在內存中的運算:

                        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)

  最后我們在腦子里模擬在內存中的運算:

                        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>

  

  如果不對請指出並給我留言。最后歡迎關注我,也歡迎技術上的交流。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM