为了方便叙述,我们先确定一些概念:
- 假设有一个整数数据类型有w位,我们可以把位向量写为 \(\vec{x}≡[x_{w-1},x_{w-2},...,x_{0}]\)
(注意最高位是w-1位)
,表示整个向量。 - 对某类数据的内部真实储存情况的零一串,记作内码;真正想表示的数,记作意码
- 将零一串\(\vec{x}\)直接读成二进制数得到数字,这种变化记作\(B2U_w(\vec x)\)
(B2U:binary to unsigned)
,即\(B2U_w(\vec x)≡Σ^{w-1}_{i=0}x_i2^i\);\(U2B_w(x)\)是它的反函数,可证这是双射。 - 为了简化表示,我们将正在以A方式编码的、意码为x的内码记作\(\vec{x}_{A_{ed}}\)。
无符号整数的编码
直接将 \(\vec{x}\) 视作二进制数,就是 \(\vec{x}\) 的无符号表示。
优点:
- 简明直观
缺点:
- 没有负数
有负数的编码
移码
为了兼容负数的朴素编码,若数据为w位,考虑意码是由内码减去\(2^{w-1}\)得到,则可以得到意码范围在\(-2^{w-1} \sim 2^{w-1}\)的编码。
优点:
- 直观,可以直接兼容移码和无符号编码的加减计算。没有两个0。
缺点:
- 移码与移码的加减运算要稍复杂。\(B2U_w(\vec{x}_{移_{ed}})+B2U_w(\vec{y}_{移_{ed}})=B2U_w(\vec{x}_{移_{ed}}+\vec{y}_{移_{ed}}-U2B_w(2^{w-1}))\) ; \(B2U_w(\vec{x}_{移_{ed}})-B2U_w(\vec{y}_{移_{ed}})=B2U_w(\vec{x}_{移_{ed}}-\vec{y}_{移_{ed}}+U2B_w(2^{w-1}))\)
原码(Sign-Magnitude)
还有一种很朴素的想法,就是将最高位作为正负标志,称为符号位。一般将符号位为0视作正数;1为负数。即 \(B2S_w(\vec{x}_{原_{ed}})≡(-1)^{x_{w-1}}Σ^{w-2}_{i=0}x_i2^i\)
优点:
- 直观朴素,容易看出负数的意码
缺点:
- “正数+负数”处理很困难,存在“+0”和“-0”两个0
反码(Ones' Complement)
正数表示不变,某正数的对应的负数储存为这个正数的反码(按位取反)
。转化公式为\(B2O_w(\vec{x}_{原_{ed}})≡-x_{w-1}(2^{w-1}-1)+Σ^{w-2}_{i=0}x_i2^i\)
优点:
- 还算直观,比较容易看出负数的意码
缺点:
- 加减处理较困难,存在“+0”和“-0”两个0
补码(two's-complement)
正数表示不变,某正数的对应的负数储存为这个正数的反码+1。转化公式为\(B2T_w(\vec{x}_{原_{ed}})≡-x_{w-1}2^{w-1}+Σ^{w-2}_{i=0}x_i2^i\)。这样任何数的加减计算都可以直接使用内码加减,如果有进位到w位(位数溢出),直接抛掉(或者说无视w位的情况,始终认定w-1是最高位)
。
优点:
- 加减处理非常方便,只有一个0。
缺点:
- 负数的意码较难直接看出,正负数表示范围差了1(负数比正数范围大1)。