數值在計算機的表現方式:
因為電路的原因,計算機只能識別1和0: 0代表低電壓;而1代表高電壓。
因此採用二進位制的方式表示數值。
二進位制數系統中,每個0或1就是一個位(bit),位是資料儲存的最小單位,一個位元組
等於8位元,就是8個bit,這是因為早期計算機使用的編碼為ASCII碼,而ASCII碼使用
的位數遠遠少於8個bit。隨著計算機的快速發展,一個位元組等於8位元已經成為規定。
有符號和無符號數值:
無符號:
1的二進位制表示 00000001
2的二進位制表示 00000010
從右到左,依次為:
2^0 -> 2^1 -> 2^2 -> 2^3 -> 2^4 -> 2^5 -> 2^6 -> 2^7
如果把以上所有數排列加起來就是255種,剛好為 2^8 - 1,範圍 0 ~ 255(無符號數不能是負數)
有符號數:
1的二進位制表示 |0|0000001
-1的二進位制表示 |1|0000001 (原碼形式)
其中,最高位的|0|和|1|表示符號位(在計算機裡面並沒有||符號,這裡為了標誌一下所以加上)
因為最高位當了符號位,所以從右到左依次是:
2^0 -> 2^1 -> 2^2 -> 2^3 -> 2^4 -> 2^5 -> 2^6
把以上的數位排列加起來就是255種,因為符號位的存在,範圍 -128 ~ 127(為什麼會有-128?)
原碼,反碼以及二補數:
原碼:是原始的機器數表示法。用最高位表示符號位,‘1’表示負號,‘0’表示正號。其他位存放該數的二進位制的絕對值。
例如:
+0 00000000 -0 10000000
+1 00000001 -1 10000001
+2 00000010 -2 10000010
................
反碼: 是將原碼除符號位取反的機器數表示方式(正數的反碼還是其原碼)。
例如:
+0 00000000 -0 11111111
+1 00000001 -1 11111110
+2 00000010 -2 11111101
...............
可以看到正數的反碼就是其原碼,而負數的反碼就是除符號位之後將其餘數值取反。
二補數: 將反碼加1的機器數表示方式(正數的二補數還是其反碼)。
例如:
+1 00000001 -1 11111111
+2 00000010 -2 11111110
...........
二補數就是將得到的反碼加上 1 。
好了, 為什麼會出現反碼和二補數????整天閒著沒事幹對吧(計算機預設用的二補數儲存。)。
原碼運算:
數學運算: 1 + 3 = 4
1的二進位制碼 00000001 ,而3則是 00000011 。
00000001
+ 00000011
————————————
00000100 = 4
數學運算: 5 + 9 = 14
5的二進位制碼 00000101 , 9的二進位制碼 00001001
00000101
+ 00001001
———————————
00001110 = 14
可以看到原碼的運算非常簡單,而且能滿足大部分需求,再看下面一個例子:
數學運算: -1 + 1 = 0
-1的二進位制碼 10000001 , 1的二進位制碼 00000001
10000001
+ 00000001
————————————
10000010 = -2
-2 不等於 0,原碼竟然不能做互補運算(一個數加上其相反數)。我的天啊!!!!
既然原碼不能,那就想個辦法解決一下,於是反碼就出來了,因為 -0 的二進位制原碼為10000000,+0 的二進位制原碼為 00000000 ,
將 -0 的二進位制碼取反,變成反碼 11111111 。(反碼是為了負數引進的,整數的反碼還是自身),如果能得到 00000000 或者 11111111的形式就解決問題!!!
最後細心的大佬發現們用反碼的運算方式就可以解決,還記得反碼就是原碼除去符號位之後其餘位數取反嗎?
反碼運算:
數學運算: -1 + 1 = 0
-1的反碼二進位制 1111110 , 1的反碼二進位制 00000001
11111110
+ 00000001
———————————
11111111 = -0 (反碼形式)
解決了互補問題,反碼真的強啊。。 開心一小會。。。。。。。。。。
再看看下面例子:
數學運算: -1 + -2 = -3
-1的反碼二進位制 11111110, -2的反碼二進位制 11111101
11111110
+ 11111101
————————————
11111011 = -4 (反碼形式)
臥槽!!!怎麼又不對了,自閉中!!!!!!!!!!!!!!
再想想辦法!!!! !!!!!!!
反碼符號取反:(此方法只是說明為什麼引進二補數,並不是正確的)
數學運算: -1 + -2 = -3
-1的反碼二進位制 11111110 , -2 的反碼二進位制 11111101 ,將兩個負數包括符號位在內的位數全取反。
得: -1的反碼符號取反二進位制碼 00000001 , -2 00000010
00000001
+ 00000010
——————————————
00000011 -> 將符號位改為1 -> 10000011 = -3 (負數原碼形式)
再來一個:
數學運算: -126 + -1 = -127
-126的反碼二進位制碼 10000001 , -1的反碼二進位制碼 11111110,將兩個負數包括符號位在內的位數全取反。
得: -126的反碼符號取反二進位制碼 01111110 , -1 00000001
01111110
+ 00000001
————————————
01111111 -> 將符號位改為1 -> 11111111 = -127 (負數原碼形式)
哇塞!!! 是不是瞬間就覺得可以啦。。。。。
開心多一會!!!!!!!!!.........................
!!!!!!!!!!!!! ..................
再看看下面的例子:
數學運算: -126 + -2 = -128
-126的反碼二進位制碼 10000001 , -2的反碼二進位制碼 11111101,將兩個負數包括符號位在內的位數全取反。
得: -126的反碼符號取反二進位制碼 01111110 , -2 00000010
01111110
+ 00000010
——————————————
10000000 -> 將符號位改為1 -> 10000000 = -0 (負數原碼形式)
哭了,怎麼有不對。這裡因為相加之後數溢位了!!!!!!
最後一個例子:
數學運算: -2 + 3 = 1
-2反碼二進位制 11111101 , 3的反碼二進位制 00000011,將兩數包括符號位在內的位數全取反。
得: -2的反碼符號取反二進位制碼 00000010, 3 11111100
00000010
+ 11111100
——————————————
11111110 將符號位改為1 -> 11111110 = -126 (負數原碼形式)
可以看見一個正數 + 一個負數 也得不到正確得結果。
由此可以看到 負數之間的減法不是主要的錯誤,主要是處理溢位錯誤和正負數之間的運算關係。
於是,大佬們都在想,既然 (正數 + 負數) 這麼難搞,有沒有一種方法把減法變成加法,順便把溢位問題解決一下。。。這樣說不定可以搞搞!!!經過漫長的不懈努力,二補數出來了!!!二補數和反碼沒有絕對的關係,只是反碼 +1剛好等於二補數!!!一定一定要記住。。
模前言:
-370 + 400 = 30 要是有個辦法,讓 400 回退 370 ,那就可以解決事情!!等等,好像把 -370 按某種特定規律變成一個數X ,X + 400 = 30 也能解決事情!!!!
就好像在一個操場跑步,操場是400米的,0 位置 開始跑步 ,跑了 400米之後又變成 0(位置角度從位移出發,位移0 和 400 在空間裡面最終位置是一樣的,所以位移是0 ),
-370 + 400 就好像 從操場逆向跑步 370米 , 這和從 400 前進 30 米完全一樣!!!!!
數論—帶餘除法
帶餘除法——設x,m∈Z,m>0,則存在唯一決定的整數q和r,使得: x = qm + r ,0<r <m
用上面操場的例子說: -370 = (-1) * 400 + r ,整個叫 -370 mod 400 ,其中 r 就是餘數。同樣 30 mod 400 = 30 ,因為 30 = (0) * 400 + r ,很容易就得到餘數為30 ,而400則稱為模。 在數論模的概念中 , -370 = 30 ,因為他們的餘數一樣,所以可以等價 。
|-370| + 30 = 400 -> 互補數相加 = 模 (|| 為數學中絕對值符號)
模運算:
假設模為2^8次方,機器碼為 100000000
數學運算: 3 + -2 = 1
因為要利用模的定義來讓數值運算後能保持在 -128 ~ 127 (最高位為符號位) , 就是以模為迴圈,來到模位置就是來到起點位置。
-2的原碼二進位制為 10000010 -> 先取絕對值 -> 00000010 , 模 - 00000010 = 互補數 -> 模 -1 - 00000010 + 1 = 互補數 , ->11111111 - 00000010 + 1 = 11111110 。
+3的原碼二進位制位 00000011 -> 00000011 ,因為前面說過,30 mod 400 = 30,正數取模餘數還是等於其本身。
11111110
+ 00000011
————————————
100000001 -> 1 (二補數形式) -> 溢位的最高位1捨棄,因為剛好等於模,相當走過了一次起點
對啦!!!終於把正負之間的運算搞定了!!
再試試負數運算:
數學運算: -1 + -126 = -127
-1的原碼二進位制為 10000001 -> 先取絕對值 -> 00000001, 模 -1 - 00000001 + 1 = 互補數 -> 11111111 - 00000001 + 1 = 11111111。
-126的原碼二進位制為 11111110 -> 先取絕對值 -> 01111110 , 11111111 - 01111110 + 1 = 10000010。
11111111
+ 10000010
————————————
110000001 -> -127 (二補數形式) 溢位的最高位1捨棄
好像負數間運算也OK了!!!!!!!!!!
再試試正數:
數學運算: 1 + 2 = 3
1的原碼二進位制為 00000001 , 2的原碼二進位制為 00000010 (正數取模還是本身)
00000001
+ 00000010
——————————————
00000011 -> 3 (二補數形式)
正數也可以啊!!!!!!!
溢位問題主要看位元組長度,短的還是會溢位,還是不可避免的,至於為什麼要把減法變成加法,是因為減法器實現比加法器難多了,為了設計成本設想。
至此原碼,反碼,二補數已經總結完了!!!,一般來說,用定義就一個數的二補數非常困難,所以用反碼加1會比較方便,但是反碼和二補數沒有絕對的聯絡!!!
如果有講解錯誤,請留言聯絡作者及時刪除,避免引導錯誤。