機器數和真值html
在學習原碼, 反碼和補碼以前, 須要先了解機器數和真值的概念.java
1.機器數:一個數在計算機中的二進制表示形式, 叫作這個數的機器數。c++
2.真值:機器數的實際值稱爲真值。 程序員
3.符號數和無符號數學習
符號數和無符號數是針對符號出現的兩種機器數表示方法。同一個二進制數,對符號數和無符號數具備不一樣的含義。編碼
符號數如: char, short ,int, long等類型的變量spa
無符號數如:unsigned char, unsigned short , unsigned int, unsigned long, 指針等類型的變量指針
原碼, 反碼, 補碼的基礎概念和計算方法htm
只有符號數纔有原碼, 反碼, 補碼blog
在探求爲什麼機器要使用補碼以前, 讓咱們先了解原碼, 反碼和補碼的概念.對於一個數, 計算機要使用必定的編碼方式進行存儲. 原碼, 反碼, 補碼是機器存儲一個具體數字的一種編碼方式.
1. 原碼:原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其他位表示值. 好比若是是8位二進制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符號位. 由於第一位是符號位, 因此8位二進制數的取值範圍就是:
[1111 1111 , 0111 1111] 即 [-127 , 127]
2. 反碼:反碼的表示方法是:正數的反碼是其自己,負數的反碼是在其原碼的基礎上, 符號位不變,其他各個位取反.
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
可見若是一個反碼錶示的是負數, 人腦沒法直觀的看出來它的數值. 一般要將其轉換成原碼再計算.
3. 補碼:補碼的表示方法是:正數的補碼就是其自己
負數的補碼是在其原碼的基礎上, 符號位不變, 其他各位取反, 最後+1. (即在反碼的基礎上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]補
[-1] = [10000001]原 = [11111110]反 = [11111111]補
對於負數, 補碼錶示方式也是人腦沒法直觀看出其數值的. 一般也須要轉換成原碼在計算其數值.
爲什麼要使用原碼, 反碼和補碼
1.使用補碼,能夠將符號位和其它位統一處理;同時,減法也可按加法來處理。
2.使用補碼, 不單單修復了0的符號以及存在兩個編碼的問題, 並且還可以多表示一個最低數. 這就是爲何8位二進制, 使用原碼或反碼錶示的範圍爲[-127, +127], 而使用補碼錶示的範圍爲[-128, 127].
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補 + [1000 0001]補 = [1000 0000]補
-1-127的結果應該是-128, 在用補碼運算的結果中, [1000 0000]補 就是-128. 可是注意由於其實是使用之前的-0的補碼來表示-128, 因此-128並無原碼和反碼錶示.(對-128的補碼錶示[1000 0000]補算出來的原碼是[0000 0000]原, 這是不正確的)
擴散思惟
byte類型的取值範圍在-128 ~ 127之間,溢出時,java、c++是如何處理的
java栗子:
byte a = (byte)128 ;
System.out.println(a);
控制檯輸出 -128,
解析:int型(int佔4個字節)128的二進制表示爲 0000 0000 0000 0000 0000 0000 1000 0000,
轉換成byte時,高階位丟失,轉換後爲 1000 0000,這是一個負數補碼,反碼爲 0111 1111,原碼爲 1000 0000,因此就是 -128
c++溢出時,聽朋友說(C++女程序員)也是高階位丟失,
總結,計算機用補碼存儲數據,經過轉換成原碼便可獲取符號和真實值,當數據溢出時,獲得的將是結果南轅北轍,後果很嚴重!
參考博客 https://www.cnblogs.com/maoypeng/archive/2018/06/01/9123826.html