二進位制運算子及補碼

2022-09-11 17:18:18 字數 3881 閱讀 7191

二進位制負數的在計算機中採用補碼的方式表示。很多人很好奇為什麼使用補碼,直接使用原碼表示多好,看上去更加直觀和易於計算。然而事實告訴我們,這種直觀只是我們人類的一廂情願罷了,在計算機看來,補碼才是它們最想要的。那麼,為什麼計算機使用補碼更好,又是如何通過補碼來計算數值的呢?

我看過網路上很多解釋補碼的文章,幾乎一致的回答就是符號位不變,其他各位逐位求反再加一。在此我想說,這些都不是根本原理。誰都知道這麼求,數電第一章就明確寫了怎麼求,關鍵是為什麼這麼算,其中的原理是什麼?

1.什麼是補碼

這個沒有找到官方定義,只進行個人定義。   

個人定義:補碼是計算機中用來表示負數,使得負數能夠使用加法器參與加法運算的一種碼。

加減是計算機中最常用的運算,加法一般使用加法器來實現,減法則使用減法器實現。那有什麼辦法可以將減法變為加法,這樣就可以讓系統只實現加法即可,答案就是補碼。

理解補碼最簡單的例子就是時鐘。

例1:假如乙個時鐘現在顯示的是10點鐘,如何將它調到6點鐘?

解:有兩種方法,一是向後撥8個小時,二是向前撥4個小時

在這個例子中,8 和 4 互為補數,也就是說4的補碼是8,8的補碼是4,而這個時鐘的模就是12

注意:可能有人會想,在往後調8個小時雖然也調到了6點,但是他實際上比原來日期多了12小時。是的,的確如此,但是你的時鐘有地方儲存了這多餘的12個小時嗎?答案是沒有,所以在你調完後,你沒有記錄這12個小時,換句話說,你把這溢位的12個小時自動捨棄了。當第二個人來檢視鬧鐘時間的時候,他看到的時間就是準的。

例2:乙個數的數值是11,他的模是16,那麼他的補碼是多少?

解:16-11 = 5,即補碼就是5。

2.模關於模沒有找到固定的定義,簡單來說模就是乙個迴圈的週期,在例1中,時鐘的乙個週期就是12,所以模是12。一周的模是7天,一天的模是24小時。模是補碼的乙個重要概念。

3.使用補碼運算

例316-13,模為32,使用補碼運算該算式。

解 (16 + (32-13))% 32 = 35 % 32 = 3 

4.使用補碼進行二進位制運算    

有看過數電基礎的都應該記得,第一章就有說明如何求二進位制補碼是如何運算的。正數的補碼即為自己,負數的補碼為符號位不變,其餘逐位求反再加1。

使用該定義,先通過例子求出數值,再對例子進行詳細講解,為什麼可以使用負數的補碼來運算。

例4   通過二進位制求15-11的值

要想讓減法變加法,必須轉換算式為 15 + (-11)

15為正數,符號位為0,二進位制表示為 01111

-11為負數,符號位為1,負數原始碼為  11011 ,補碼符號位不變,其餘逐位求反再 +1,即 10101

所以 15 + (-11) = 01111 + 10101 = 100100 捨棄最高位(與高位址位概念不同)溢位位,即00100,即+4

這是乙個最簡單的補碼演算法運算的例子,卻有很多不解之處。

1.為什麼負數 (-11 )逐位求反再+1就可以代表原來的數?

2.為什麼高位捨棄

3.為什麼符號位能夠參與運算

先看問題1,-11 先不考慮符號位,觀察11的二進位制表示,11使用二進位制表示是 1011,將1011 逐位求反 得到 0100,因為是逐位求反,1011 +0100 = 1111 ,而1111 + 1 = 10000,發現了什麼?10000是四位2二進位制數的模。為什麼10000是4位二進位制數的模呢?原理也很簡單,4位暫存器最高能表示什麼數?即0b1111 = 15 , 15 +1 =16 即溢位低四位歸 0,所有模為16。

所以不管幾位二進位制數,取反後得到的值加原碼會剛好的到所有的位都是1的二進位制數,再加一就剛好進製得到模。所以取反加一是無論如何都能取到補碼的。比如 :(原)101 +  (補)((反)010 +1) = 8 ,(原)10 + (補)((反)01 +1)= 4。

所以,負數符號位不變,其餘逐位求反 +1 只是算出補碼最簡單的方法,而不是理論基礎。

前面提到過,使用補碼代替原碼,計算後模掉溢位得到數值就可以得到計算的值了。

再看問題2,為什麼高位捨棄,這個問題其實在例1中已經做了說明,因為你沒有儲存這個高位的空間,用最簡單的解釋來解釋就是,乙個4位的暫存器,只能儲存資料的低四位,最高第五位沒地方放,就像例1中多出來的12小時,沒有地方儲存,那麼就丟棄了,反正結果正確就行。可能有人會問,你說丟棄就丟棄嗎,丟了你怎麼保證是正確的?

重新再看一次例4,現在考慮符號位,將符號位加入運算。

15 - 11 = 15 + (-11),其中 -11 為 11011(加了一位符號位,所以模為 16 * 2^1) 他的補碼為 10101 = 21

所以 15 -11 變為 15 +21 = 36 (01111 + 10101) ,想想看,原先是減乙個數,變換後卻變成了乙個比減數更大的加數了,能不溢位嗎。所以要模掉溢位位 36 % 32 = 4 。仔細觀察被模數36 = 1 00100 你會發現,在資料高2位以前的所有高位都是32的倍數,所以用32進行模運算就會全部清0,這就是為什麼高位可以直接捨棄的原因,因為高位永遠會是模的倍數。

最後看問題3,為什麼符號位能夠參與運算,可能在這前面一直被符號位困擾,為什麼參與運算就沒有問題,看了這裡的解釋,我相信你講不會再被困擾。

符號位對於我對二進位制補碼的理解產生了很大的阻礙,我不明白為什麼符號位可以參與運算,而且算出來還是對的。花了不少時間理解了符號位的含義。我想說,符號位不變,其餘逐位求反 +1 這個定義很差。

首先放棄符號位就是計算機表示正數和負數用的這個思維,改成這樣理解,就會非常清晰:在有符號的資料型別中,第一位如果是0,那麼這個數值是正數原碼,第一位如果是1,那麼這個數值是負數補碼,這個數值是計算所得,而不是計算機設定的如此。

然後放棄負數補碼符號位不變,其餘逐位求反再+1這個方法,使用如下負數補碼的求法。乙個二進位制數值如果是正數,那麼將不變。如果是負數,那麼這個二進位制數最高位加一位0(如: 1010 變為 01010 ,位數變高一位,模需要乘2,即由16變32),對該數求補碼(01010 求補碼 10110) 。是不是發現,所謂的符號位不變,其餘逐位求反再加一和 在數值前面再加一位0,再所有位求反再+1的效果是一樣的,只要求反,最高位0肯定會變成1。一旦知道第一位是0或者1,也就確定了他是正數還是負數了,採用這種理解法,運算子可以加入運算也就理所當然了。(被減數 + 負數補數)% 負數補數的模 = 帶符號計算值 這樣的計算方式能保證所有的符號位都能參與運算。而符號位不變,其餘取反+1的解釋顯的符號位非常難以理解。

最後再看下重新思考這個運算思路,在運算中,如果遇到加法運算子,則直接運算子,如果遇到減法運算子,檢視減數是正數還是負數,如果是負數,從補碼反求原始碼,加入計算,如果遇到正數,則最高位加一位0,取反 +1 求補碼,加入運算。

到這裡補碼的原理就差不多講清楚了,無非是使用模進行轉化,但是我們站在十進位制的角度,去看二進位制的東西,的確會顯得相當費解。

內容有相互巢狀成分,閱讀後回顧前面的內容可能會更加深入理解。

還有很多特殊情況沒有考慮,只講解了最核心的內容。

以上內容**於:

二進位制中的運算子

1、按位與運算子(&)

規則: 0 & 0 = 0; 0 & 1 = 0; 1 & 1= 1;   即,兩位同為1即為1,否則0.

例如:   3 & 5 = 1    ---->  0011 & 0101 = 0001  即為1。

2.按位或預算符 (|)

規則: 0 | 0 = 0; 0 | 1 = 1;1 | 0 = 1; 1 | 1 = 1;  即,兩位同為0即為0,否則1。

例如: 3 | 5 = 7     --->  00000011 | 00000101 = 00000111  即為 7。

規則:0^0 = 0,0^1=1,1^0=1,1^1=0 參加位運算的兩位只要相同為0,不同為1

例子:3^5 = 6(00000011^00000101=00000110)

特別的任意數 ^ 0 = 任意數.

規則:二進位制位0變為1,1變為0

規則:相當於乘以2

規則:相當於除以2

二進位制 補碼 運算

問乙個基本的問題。負數在計算機中如何表示?舉例來說,8在計算機中表示為二進位制的1000,那麼 8怎麼表示呢?很容易想到,可以將乙個二進位制位 bit 專門規定為符號位,它等於0時就表示正數,等於1時就表示負數。比如,在8位機中,規定每個位元組的最高位為符號位。那麼,8就是00001000,而 8則...

二進位制補碼運算

二進位制負數的在計算機中採用補碼的方式表示。很多人很好奇為什麼使用補碼,直接使用原碼表示多好,看上去更加直觀和易於計算。然而事實告訴我們,這種直觀只是我們人類的一廂情願罷了,在計算機看來,補碼才是它們最想要的。那麼,為什麼計算機使用補碼更好,又是如何通過補碼來計算數值的呢?我看過網路上很多解釋補碼的...

二進位制位運算子

二進位制位運算子用於直接對二進位制位進行計算,一共7個。i i 0 上面這行 的意思就是將i 不管是整數或小數 轉為32位整數。利用這一特性,可以寫乙個函式,將任意數值轉為32位整數。function toint32 x toint32 1.001 1 toint32 1.999 1 toint32...