理解数值表示法:原码、补码、反码与移码详解
1. 真值和机器数
真值:数的实际值,用正负号和绝对值的某进制形式来表示,如+1010,-12,-FFFF等.
机器数:真值在计算机中的二进制表示,特点是符号数字化且数的大小受机器字长限制,其表示形式有原码,补码,反码,移码等.
2. 原码.
1). 定点小数:
\[{x_{[{\rm{原}}]}} = \left\{ {\begin{array}{*{20}{l}}
{x,0 \le x < 1}\\
{{2^0} - x = {2^0} + \left| x \right|, - 1 < x \le 0}
\end{array}} \right.\]
(其中x[原]是机器数,x是真值,最高位为符号位,下同.)
表示范围:
\[\max = 1 - {2^{ - n}},\min = - (1 - {2^{ - n}})\]
(n是指x除符号位的位数,下同)
如: x=+0.1011, x[原]=0.1011
x=-0.1011, x[原]=1.1011
2). 定点整数:
\[{x_{[原]}} = \left\{ \begin{array}{l}
x,0 \le x < {2^{\rm{n}}}\\
{2^n} - x = {2^n} + |x|, - {2^n} < x \le 0
\end{array} \right.\]
表示范围:
\[\max = {2^n} - 1,\min = - ({2^n} - 1)\]
如:x=+1011,x[原]=01011
x=-1011,x[原]=11011
3). 特点:
原码实质上为符号位加上数的绝对值,0正1负;
原码零有两个编码,+0和 -0编码不同,表示不唯一;
原码加减运算复杂,乘除运算规则简单;
原码表示简单,易于同真值之间进行转换.
3. 补码
1). 定点小数:
\[{x_{[补]}} = \left\{ \begin{array}{l}
x,0 \le x < 1\\
2 + x = 2 - |x|, - 1 \le x \le 0
\end{array} \right.(\bmod 2)\]
表示范围:
\[\max = 1 - {2^{ - n}},\min = - 1\]
如:x=+0.1011, x[补]=0.1011
x=-0.1011, x[补]=10+x=10.0000-0.1011=1.0101
2). 定点整数:
\[{x_{[补]}} = \left\{ {\begin{array}{*{20}{l}}
{x,0 \le x < {2^{\rm{n}}},0 \le x < {2^n}}\\
{{2^{n + 1}} + x = {2^{n + 1}} - |x|, - {2^n} \le x \le 0}
\end{array}(\bmod {2^{n + 1}})} \right.\]
表示范围:
\[\max = {2^n} - 1,\min = - {2^n}\]
如:x=+1011,x[补]=01011
x=-1011, x[补]=2^5 – |-1011|=100000 – 1011=10101
3). 特点
负数补码实质上为原码除符号位按位取反再加1
补码最高一位为符号位,0正1负;
补码零有唯一编码;
补码能很好用于加减运算;
补码满足x[补]+(-x)[补]=0;
补码最大的优点在于能够将减法运算转换成加法运算,其中符号位参与运算,它满足:
\[\begin{array}{*{20}{l}}
{{{(x{\rm{ }} + {\rm{ }}y)}_{\left[ 补 \right]}} = {\rm{ }}{x_{\left[ 补 \right]}} + {\rm{ }}{y_{\left[ 补 \right]}}}\\
{{{(x{\rm{ }} - {\rm{ }}y)}_{\left[ 补 \right]}} = {\rm{ }}{x_{\left[ 补 \right]}} + {\rm{ (}} - y{)_{\left[ 补 \right]}}}
\end{array}\]
例如:
\[\begin{array}{l}
x = {11_{[10]}} = {1011_{[2]}},y = {5_{[10]}} = {0101_{[2],}}\\
{(x - y)_{[补]}} = {x_{[补]}} + {( - y)_{[补]}} = 01011 + 11011 = 100110(溢出) = 00110 = {6_{[10]}} = x - y\;\;
\end{array}\]
4). 补码和原码转换.
正数:x[补]=x[原]
负数:按位取反,末位加1(符号位除外)
如:x= -1001001, x[原]=11001001,x[补]=10110110+1=10110111
5). 补码和真值的转换
\[{\rm{补码}}\left\{ \begin{array}{l}
{\rm{符号 = }}0{\rm{ - 正}},{\rm{余下为数值部分}}\\
{\rm{符号 = }}1{\rm{ - 负}},{\rm{余下求补为数值部分}}
\end{array} \right.\]
4. 反码
1). 定点小数
\[{x_{[{\rm{反}}]}} = \left\{ {\begin{array}{*{20}{l}}
{x,0 \le x < 1}\\
{(2 - {2^{ - n}}) + x = 2 + x - {2^{ - n}}, - 1 < x \le 0}
\end{array}} \right.\]
范围:
\[\max = 1 - {2^{ - n}},\min = - (1 - {2^{ - n}})\]
如:x=0.1011,x[反]=0.1011
x=-0.1011,x[反]=1.0100
2). 定点整数
\[{x_{[{\rm{反}}]}} = \left\{ {\begin{array}{*{20}{l}}
{x,0 \le x < {2^{\rm{n}}}}\\
{({2^{n + 1}} - 1) + x = {2^{n + 1}} + x - 1, - {2^n} < x \le 0}
\end{array}} \right.\]
范围:
\[\max = {2^n} - 1,\min = - ({2^n} - 1)\]
如:x=1011,x[反]=01011
x=-1011,x[反]=10100
3). 特点
负数反码实质上为原码除符号按位求反,也就是补码-1;
反码零有两个编码,+0 和 -0 的编码不同;
反码难以用于加减运算;
反码的表示范围与原码相同.
5. 移码:用于表示浮点数的阶码
1). 定义
\[x[移] = {2^n} + x, - {2^n} \le x < {2^n}\]
范围:
\[\max = {2^{n + 1}} - 1,\min = 0\]
如:x=+1011,x[移]=11011
x=-1011,x[移]=00101
2). 特点
移码中符号位表示的规律与原码,补码,反码相反——"1"正"0"负;
移码为全0时所对应的真值最小,为全1时所对应的真值最大,移码的大小直观地反映了真值的大小,这有助于两个浮点数进行大小比较;
真值0在移码中的表示形式是唯一的;
移码把真值映射到一个正数域,所以可将移码视为无符号数,直接按无符号数规则比较大小;
同一数值的移码和补码除最高位相反外,其他各位相同.
3). 移码和补码转换
\[\begin{array}{l}
{x_{[补]}} = \left\{ \begin{array}{l}
x,0 \le x < {2^n}\\
{2^{n + 1}} + x, - {2^n} \le x \le 0
\end{array} \right.\\
{x_{[移]}} = {2^n} + x, - {2^n} \le x < {2^n}\\
{x_{[移]}} = \left\{ \begin{array}{l}
{x_{[补]}} + {2^n},0 \le x < {2^n}\\
{x_{[补]}} + {2^n} - {2^{n + 1}} = {x_{[补]}} - {2^n}, - {2^n} \le x \le 0
\end{array} \right.
\end{array}\]
推荐阅读
-
理解数字逻辑基础:原码、反码与补码详解
-
数的机器码表示:原码、反码、补码、变形补码、移码和浮点数编码-数学定义:例:+111的原码为0111,-101的原码为1101 (2) 纯小数的原码表示 纯小数的原码首位同样为符号位,后面的数值则表示小数的尾数,纯小数的整数位为默认为0无需表示。 例:+0.111的原码为0111,-0.101的原码为1101 可以看到,+111和+0.111的原码同为0111,这是因为约定的小数点位置不同,整数的原码的小数点约定在末尾,纯小数的原码的小数点约定在数值的最前面,这样通过约定小数点的位置来表示数的方法就称为定点数表示法,约定小数点位置实际上就是约定编码中每一位的权重。 二、反码 正数的反码与其原码相同。 负数的反码是其对应原码的符号位不变,数值位按位取反。 数学定义:例: 真值 +111 -101 +0.111 -0.101 原码 0111 1101 0111 1101 反码 0111 1010 0111 1010 三、补码 原码虽然转换很简单,但是在做减法时操作很复杂(减不够还要借位),因此计算机在做加负数操作时会先将负数的原码转换为补码再做加法。 先举个栗子,假设时钟现在是9点钟,我把时针往回拨3个小时是6点钟,或者顺时针往后拨9个小时还是6点钟,也就是说9-3的结果等同于9+9(mod 12),对于模数12,-3的补码为+9,这就引申出了一种将减法转换为加法的思想,把减去一个正数视为加上一个负数(例如9+(-3)),再将负数转换为对应的补码,最后就可以和补码做加法了,若结果超出了模数则丢弃一个模数即可。 如图所示:9减去灰色的部分(-3)就等同于加上蓝色的部分,即-3的补码即为蓝色部分的长度9(mod 12)。即补码=模数+真值(超出模数则舍弃一个模数) (1) 整数的补码表示 对于一个n位的二进制真值x,则取模数为2^(n+1),若x为正数则补码和原码相同(加上一个模数又需舍弃一个模数 故相同),若为负数则补码为模数加上x。相对于原码,补码这里的首位就不仅代表原数真值的符号了,也是补码自己的一个数值位。 取模数为2^(n+1)是因为在需要舍弃模数时只需要舍弃运算结果(二进制数)的最高位即可,这在计算机中很容易实现 数学定义:例:三位二进制数的模数2^4就是10000,故+111的补码为0111(即10000 + 111 = 0111 (舍弃模数位)),-101的补码为1011(即10000 - 101 = 1011) 补码运算示例:那么+111 - 101 = +111 + (-101) = 0111 + 1011 = 10010,运算结果只保留后四位(即舍弃模数位),故计算结果为0010。这样就通过加法实现了减法运算。 补码可表示数据范围:由数学定义可知,n位二进制补码可表示的数据范围为 -2n-1~2n-1-1。以8位的byte类型数为例,可表示的数据范围为 -27~27-1,即-128至+127,最小负数-128(补码:1000 0000),最大负数-1(补码:1111 1111),0(补码:0000 0000),最小正数1(补码:0000 0001),最大正数127(补码:0111 1111)。 由补码求真值:正数的补码即为原码即为真值,负数的真值由计算规则可知 负数真值= - (模数 - 补码),以补码1111 1111为例,其真值 = - (1 0000 0000 - 1111 1111) = - 0000 0001 = -1 (2) 纯小数的补码表示 对于一个纯小数x,则取模数为2^1,正数的补码和原码相同,负数的补码为模数2加上x。同样补码的首位不仅代表原数真值的符号,也是补码的数值位。 数学定义:例:纯小数的模数2就是10,故+0.111的补码为0111,-0.101的补码为1011(小数点约定在符号位后) 计算机中求补码的规则 可以注意到求负数的补码时还是要做减法,这在计算机中就很不方便了,但是通过其数学定义可以看到无论是整数还是纯小数,负数的补码都等于反码的末尾加1,而这又等同于原码数值位从右向左遇到第一个1后,这个1左边的数值位都按位取反,故实际计算机中求补码的规则如下:正数的补码等于原码负数的补码等于原码的数值位从右向左的第一个1左边的所有数值位按位取反(例:byte类型值-6的原码为1000 0110,则其补码为1111 1010) 四、变形补码 两个补码在运算时可能会溢出从而产生错误的结果,比如0111+0101 = 1100,两个正数相加反而得到了一个负数,那么在计算机中要如何判断运算结果是否溢出了呢,这就引申出了变形补码。从直观上看,相对于补码来说变形补码就是用两位来表示符号位,00表示正数,11表示负数。运算结果符号位为01表示正溢出,10表示负溢出。
-
代码详解:各类数值表示法 - 原码、反码、补码与浮点数的转换
-
理解数值表示法:原码、补码、反码与移码详解
-
电脑构造基础:原码、补码、反码与移码详解
-
理解无符号数与有符号数:原码、反码、补码与移码的基本概念
-
深入理解原码、反码、补码与移码的各种概念与区别
-
轻松掌握软考知识点1:理解各类电脑数字码制 - 原码、反码、补码、移码与奇偶检验码、海明码及循环冗余码详解