[負(fù)數(shù),補(bǔ)碼]
早先再CSDN寫過一篇文章:最近在看python,再次復(fù)習(xí)一下:
硬件里只有固定寬度的二進(jìn)制位,負(fù)數(shù)不是“單獨(dú)的東西”,而是用補(bǔ)碼(二進(jìn)制的兩補(bǔ))來編碼在同樣的位寬里。核心點(diǎn)如下。
兩補(bǔ)表示
- 有符號(hào)整數(shù)用兩補(bǔ)表示;最高位是“符號(hào)位”但本質(zhì)上有權(quán)值。
- 對(duì)于
n位的兩補(bǔ)數(shù),位向量b[n-1] ... b[0]的數(shù)值是:value = -b[n-1]*2^(n-1) + Σ_{i=0..n-2} b[i]*2^i
- 取值范圍:
[-2^(n-1), 2^(n-1)-1];比如 8 位是[-128, 127]。
負(fù)數(shù)如何得到
- 計(jì)算規(guī)則(兩補(bǔ)):對(duì)正數(shù)的二進(jìn)制按位取反,再加 1。
- 等價(jià)規(guī)則:
-x的位模式是2^n - x(在n位寬下取模)。 - 例子(8 位):
+5→00000101- 取反 →
11111010,加 1 →11111011,所以-5→11111011 -1→11111111(因?yàn)?256 - 1 = 255)- 最小值
-128→10000000;最大值+127→01111111
為什么用補(bǔ)碼
- 加法器只需一種電路就能完成加減(減法變加法)。
- 溢出“環(huán)繞”行為統(tǒng)一,最高位參與權(quán)值計(jì)算,符號(hào)擴(kuò)展自然成立。
有符號(hào) vs 無符號(hào)
- 無符號(hào):全位都是正權(quán)值,范圍
[0, 2^n - 1]。 - 有符號(hào)(兩補(bǔ)):最高位是負(fù)權(quán)值,范圍
[-2^(n-1), 2^(n-1)-1]。 - NumPy:
'iN'是有符號(hào)(如i4=int32),'uN'是無符號(hào)(如u4=uint32)。
與 NumPy/Pandas 的關(guān)系
- 你在
l02.py里用的dtype=[('a','i4'),('b','f4'),('c','U10')]:'a'是int32(兩補(bǔ)),'b'是float32,'c'是最多 10 個(gè) Unicode 字符。
- 轉(zhuǎn)成
DataFrame時(shí),a列保持int32,b列是float32,c列顯示為<U10或object(取決于版本)。
示例代碼
import numpy as np
def bin8(x):
# 以 8 位二進(jìn)制顯示底層位模式(統(tǒng)一用無符號(hào)視圖)
return format(np.uint8(x), '08b')
print("8 位兩補(bǔ)表示示例:")
print("+5 ->", bin8(5)) # 00000101
print("-5 ->", bin8(-5)) # 11111011
print("-1 ->", bin8(-1)) # 11111111
print("+127->", bin8(127)) # 01111111
print("-128->", bin8(np.int8(-128))) # 10000000
# 有符號(hào) vs 無符號(hào)賦值與環(huán)繞
a_int8 = np.int8(-1)
a_uint8 = np.uint8(-1) # 取模 256,得到 255
print("int8(-1) 數(shù)值:", a_int8, "位模式:", bin8(a_int8)) # -1, 11111111
print("uint8(-1) 數(shù)值:", a_uint8, "位模式:", bin8(a_uint8)) # 255, 11111111
# 溢出(環(huán)繞)示例:int8 的 127 + 1 -> -128;uint8 的 255 + 1 -> 0
print("int8 溢出: 127 + 1 =", np.int8(127) + np.int8(1), "位模式:", bin8(np.int8(127) + np.int8(1)))
print("uint8 溢出: 255 + 1 =", np.uint8(255) + np.uint8(1), "位模式:", bin8(np.uint8(255) + np.uint8(1)))
# 符號(hào)擴(kuò)展示例:從 8 位到 16 位
v8 = np.int8(-5)
v16 = v8.astype(np.int16)
print("符號(hào)擴(kuò)展 int8(-5) -> int16:", v16)
print("16 位位模式:", format(np.uint16(v16), '016b')) # 1111111111111011

浙公網(wǎng)安備 33010602011771號(hào)