部分參考了https://www.cnblogs.com/songdechiu/p/5397070.html
一、補碼的優點
1、可以將減法轉化為加法,在計算機中只保留加法
2、將符號位參與運算
二、如何實現?
我們先以鍾表為例子,假設現在的標准時間為4點整,而有一個鍾的時間為7點整。我們可以將時針逆時針旋轉3格,或者將時針順時針旋轉9格,如圖。

7-3=7+9=4 mod(12)
上述式子為一個同余式,同余式的標准定義為
a ≡b (mod n)
即同余式兩邊的數值,對n進行取余后的數值相等。
從上述例子我們可以得到靈感,即用一個正數來替代負數(上述例子中用9替代-3)從而將減法轉化為加法。
在計算機中,我們應該如何進行這種替換?
我們應先明確一些概念,如原碼表示,加法器的溢出,負數取余。
原碼表示:最高位為符號位
正數:符號位為0,剩余的為數值
如用8位表示一個數,則+8為 0000 1000(2)
負數:符號位為1,剩余的為數值
如用8位表示一個數,則-8為 1000 1000(2)
采用原碼來進行計算機的運算,將會非常復雜,因為將會有很多邏輯判斷。
如兩數相加時,同好則數值相加;不同號則相減,而且還要比較數值部分的絕對值的大小。
所以人們找到了補碼的表示方法。
加法器的溢出:
假如一個加法器為8位的加法器,當和的值超過了 1111 1111(2),那么高位將被丟棄。
如 1111 1111(2)+ 1111 1111(2)= 1111 1110(2)
也就是說這個加法器只能表示0-255,即256為一個輪回,從我們的角度來看的話,這個加法器對結果進行取余,其模為256。
讓我們推廣到一般情況,n位加法器
xnxn-1……x0,即只能表示0-2n-1,即2n為一個輪回,從我們的角度來看的話,這個加法器對結果進行取余,其模為2n。
(原文有錯誤,因此標紅顏色,這里已經修改)及256一個輪回,即2的8次為一個輪回,而不是
負數的取模:
我們應該先探討一下負數的取模操作,我們知道取模公式如下所示:
x mod y = x - y* [x/y]
注:[x/y]為下取整符號
上邊我們說到要用正數來取代負數從而達到,將減法轉化為加法,那么應該怎么取代,關系式是怎么樣的?
對於一般二進制數xnxn-1……x0進行探討,從上邊的討論我們知道,對這個二進制數進行加減操作時,最終的結果都將進行模為2n的取余操作。我們假設這個二進制數值為[x]補,其代表的真值為x。
1、當xn為0時,[x]補=x,范圍為0 - 2n-1;即0~127是整數
2、當xn為1時,其代表的為負數x,我們知道這里應該用一個正數[x]補來取代負數x,並且使模為2n的同余式相等。
讓我們先來討論-1,-1對2n進行取余,即
-1 mod 2n = -1 - 2n*(-1) = 2n- 1
[2n - 1]補 = -1
所以我們用2n - 1替代-1 舉例2^8-1=255,11111111 代表-1,可以從ads1259的datasheet中看出端倪

則,對負數x為,
x mod 2n = x - 2n*(-1) = 2n + x
[2n + x]補 = x
x的范圍為-1至-2n-1
,即-1到-128
所以我們用2n - 1替代x
——以補碼定義式為基礎,沿數軸列出典型的真值、原碼與補碼表示,可清楚了解補碼的有關性質——

這就是為什么8位二進制, 使用原碼或反碼表示的范圍為[-127, +127], 而使用補碼表示的范圍為[-128, 127].
因為機器使用補碼, 所以對於編程中常用到的32位int類型, 可以表示范圍是: [-231, 231-1] 因為第一位表示的是符號位.而使用補碼表示時又可以多保存一個最小值.
總結:這里可以根據很多adc的芯片來進行學習二進制的補碼,很多能夠采集正負電壓的adc芯片都采用二進制的補碼來表示。
比如在ti的ads1118中,有如下溫度傳感器的采集數據說明

以及

很簡單,如何得到負數的溫度(LSB),可以這么計算,因為這個溫度傳感器adc的精度是14位,最高位是符號位,假如采集得到寄存器是0x3ce0,那么,我們可以這么計算真正的負數大小:0x4000-0x3ce0=0x320,說明有這么多付的LSB,因此,還是比較簡單的,
同樣,ads1259上面,-1是用ffffff來表示的,那么0x1000000-0xFFFFFF=1,說明是一個LSB。
