計算機二進位制中的原碼,反碼,補碼
阿新 • • 發佈:2020-11-23
> **公號:碼農充電站pro**
> **主頁:**
計算機最基本的工作是處理資料,而資料的最底層表現形式是二進位制,並非是我們人類熟悉的十進位制。可以這麼認為,計算機其實是很“笨的”,它只理解二進位制資料。
今天,主要介紹計算機是怎樣做加減運算的。你可能會想,加減運算?這麼簡單的事情,還用介紹?也許還真不是你想的那樣。
計算機的運算是由CPU 完成的,而CPU 只會做加法運算,不會做減法運算,那計算機怎樣完成減法工作呢?
### 1,二進位制數
我們先來看看二進位制數。
二進位制數是由0,1 組成的,比如:
- 十進位制的5,用二進位制表示是 101。
- 十進位制的7,用二進位制表示是 111。
數字由正數和負陣列成。為了表示正負數,計算機中就有了**有符號數**和**無符號數**之分:
- 無符號數:英文為 `unsigned`,只能表示正數。
- 有符號數:英文為`signed`,即能表示正數,又能表示負數。
> **C/C++** 語言中的數字有**有符號數**和**無符號數**之分。
> **Java** 語言所有的數字都是**有符號數**。
假如,我們用 4 位二進位制,來表示無符號數,也就是隻表示正數,能表示的範圍是 `0 到 15`,轉換關係如下表:
| 十進位制數 | 二進位制數 |十進位制數 | 二進位制數 |
|--|--|--|--|
| 0 | 0000 |8 | 1000 |
| 1 | 0001 |9 | 1001 |
| 2 | 0010 |10 | 1010 |
| 3 | 0011 |11 | 1011 |
| 4 | 0100 |12 | 1100 |
| 5 | 0101 |13 | 1101 |
| 6 | 0110 |14 | 1110 |
| 7 | 0111 |15 | 1111 |
有符號數,即要表示正數,也要表示負數。
要用二進位制表示有符號數,需要用二進位制的**最高位**來表示符號,`0` 表示`正`,`1` 表示`負`。所謂的最高位,也就是最左邊那一位。
用 4 位二進位制,來表示有符號數,能表示的範圍是 `-8 到 7`,轉換關係如下表:
| 十進位制數 | 二進位制數 |十進位制數 | 二進位制數 |
|--|--|--|--|
| 0 | `0`000 |**-8** | **`1`000** |
| 1 | `0`001 |-1 | `1`001 |
| 2 | `0`010 |-2 | `1`010 |
| 3 | `0`011 |-3 | `1`011 |
| 4 | `0`100 |-4 | `1`100 |
| 5 | `0`101 |-5 | `1`101 |
| 6 | `0`110 |-6 | `1`110 |
| 7 | `0`111 |-7 | `1`111 |
上表中的最高位的符號位,已標紅。
> 要注意,對於有符號的4 位二進位制 ----`1000` 不是 `-0`,而是 `-8`。
可以總結出,對於`N` 位的二進位制數:
- 無論是表示**有符號數**還是**無符號數**,都能表示`2^N` 個數字。
- 若用於表示**無符號數**,則能表示的範圍是 `[0, 2^N - 1]`。
- 若用於表示**有符號數**,則能表示的範圍是 `[-2^(N-1), 2^(N-1) - 1]`。
- **需要注意**,在有符號數中,對於符號位是 `1`,後面 `N-1` 位全是 `0`,這種情況表示的是 `-2^(N-1)`(也就是所能表示的最小值),而不是 `-0`。
- 實際上是將`-0` 這種情況解釋成了`最小值`,否則就會出現 `+0` 和 `-0` 兩個`0`。
### 2,二進位制原碼
上面介紹到的二進位制就是原碼形式。
**原碼就是除符號位外的其他位,儲存該二進位制數的絕對值。**
***用原碼進行加法計算***
計算機中的數字運算都會先轉成二進位制數再進行計算。
我們用原碼來計算加法,用4 位二進位制數來計算 `3 + 2`,過程如下:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201121115329554.png?#pic_center)
可以看到,用原碼計算加法是沒有問題的。
***用原碼進行減法計算***
我們再用原碼來計算減法,因為CPU 只會計算加法,所以計算減法時,會將減法轉換成加法。
比如,用4 位二進位制數來計算計算 `3 - 2`,會將其轉換成 `3 + (-2)`, 過程如下:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201121120031179.png?#pic_center)
可以看到 `3-2` 計算出來的結果是 `-5`,顯然是錯誤的。
所以,用二進位制原碼來計算減法是行不通的。實際上,計算機計算減法用的是**補碼**。
在介紹補碼之前,我們先來看下什麼是**溢位**。
### 3,數字溢位
計算機中數字的表示是需要記憶體空間的,不同型別的數字所能佔用的空間是不一樣的。
比如,在Java 語言中`short` 型別佔用 2 個位元組,`int` 型別佔用 4 個位元組。
> 一個位元組等於 8 位。
既然空間大小是有限制的,所以計算機中的數字也是有範圍的,即**上限**和**下限**,如果數字超出限制,就會產生**溢位**。超出上限叫**上溢位**,超出下限叫**下溢位**。***而溢位的部分會直接被捨去***。
就像我們在上文中介紹的,對於`N` 位二進位制**有符號整數**,所能表示的範圍是 `[-2^(N-1), 2^(N-1) - 1]`。
由於溢位的部分會被捨去,那麼最大值加1,將發生上溢位,變為最小值;最小值減1,將發生下溢位,變為最大值。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201121124424444.png?#pic_center)
我們用**Java** 中的`int` 型別來驗證,**Java** 中`int` 型別的最大、最小值分別是:
- 最大值:`Integer.MAX_VALUE`,是 `2147483647`。
- 最小值:`Integer.MIN_VALUE`,是 `-2147483648`。
用下面程式碼驗證:
```java
System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE); // true
System.out.println(Integer.MIN_VALUE - 1 == Integer.MAX_VALUE); // true
```
這兩行程式碼的輸出均為`true`,說明最大值加1 變為最小值,最小值減1 變為最大值。
所以,在計算機中,只要一個整數的型別確定了,那麼它所能佔用的記憶體空間大小也就確定了,從而它所能表示的數字範圍也就確定了。那麼不管給這個整數加多大的數字,或者減多大的數字,最終的結果都只能在這個範圍內旋轉。
就像錶盤一樣,當錶針走過最大值的時候,就變成了最小值。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201121125009922.png?#pic_center)
同樣,這也等同於數學中的**取餘**運算。只要分母確定了,不管分子是多大,或者多小的數字,最終的結果也都是在一個確定的範圍之內。
比如我們對十進位制`5` 進行**取餘**計算,那麼最終的結果都是在`[0, 4]` 範圍之內,如下:
- `0 % 5 = 0`
- `2 % 5 = 2`
- `397 % 5 = 2`
- `99999 % 5 = 4`
可以總結出,對數字`N` 進行取餘,`N >= 2` 且為整數,那麼結果都在 `[0, N-1]` 範圍之內。
### 4,二進位制反碼與補碼
知道了**溢位**,就可以介紹CPU 如何計算減法了。CPU 的減法運算使用了二進位制補碼,補碼實際上就是採用了**溢位**的原理。
我們直接給出**反碼與補碼**的定義:
- 反碼定義:**正數的反碼等於其原碼,負數的反碼是其原碼除符號位外,按位取反。**
- 補碼定義:**正數的補碼等於其原碼,負數的補碼是其反碼加1。**
比如下面的幾個數字:
| 十進位制數 | 2 | 3 | -2 |-5 |
|--|--|--|--|--|
| **二進位制原碼** | **0010** | **0011** | **`1`010** | **`1`101** |
| **二進位制反碼** | **0010** | **0011** | **`1`101** | **`1`010** |
| **二進位制補碼** |**0010** | **0011** | **`1`110** |**`1`011**
我們用`4` 位二進位制補碼來計算 `3+(-2)`,如下:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201121215718758.png?#pic_center)
最高位的`1` 發生上溢位,直接被捨去,所以結果是正確的。
所以,要記住,**真實的計算機中的二進位制是用補碼錶示的,而不是原碼**。
### 5,總結
本篇文章主要介紹了:
- CPU 只能做加法,不能做減法,減法要轉成加法做計算。
- 二進位制數字有三種表示方式:
- 原碼:除符號位外的其他位,儲存該二進位制數的絕對值。
- 反碼:正數的反碼等於其原碼,負數的反碼是其原碼除符號位外,按位取反。
- 補碼:正數的補碼等於其原碼,負數的補碼是其反碼加1。
- 計算機中的數字採用二進位制補碼錶示,而不是原碼錶示。
- 補碼採用了溢位的原理。
- 計算機中的數字是有範圍限制的,超出限制會發生溢位。
- 超出上限叫做上溢位。最大值加1會發生上溢位,變為最小值。
- 超出下限叫做下溢位。最小值減1會發生下溢位,變為最大值。
(本節完。)
---
**推薦閱讀:**
[***決策樹演算法-理論篇***](https://www.cnblogs.com/codeshell/p/13948083.html)
[***決策樹演算法-實戰篇***](https://www.cnblogs.com/codeshell/p/13984334.html)
[***樸素貝葉斯分類-理論篇***](https://www.cnblogs.com/codeshell/p/13999440.html)
[***設計模式之高質量程式碼***](https://www.cnblogs.com/codeshell/p/13968620.html)
[***如何高效使用VIM***](https://www.cnblogs.com/codeshell/p/12726516.html)
---
歡迎關注作者公眾號,獲取更多技術乾貨。
![碼農充電站pro](https://img-blog.csdnimg.cn/20200505082843773.png?#pic