计算机中的数(二)之原码、补码、反码及其转换

上一篇:计算机中的数之一 无符号数与有符号数

原码

原码是机器数中最简单的一种表示形式,符号位为0表示正数,符号位为1表示负数,数值位即是真值的绝对值,故原码又称为带符号的绝对值表示。譬如101的原码是0,101。我们用逗号 " , " "," ","作为符号位和数值部分的分隔符。
原码正数定义
[ x ] 原 = { 0 , x 2 n > x ≥ 0 2 n − x , 0 ≥ x > − 2 n [x]_原=\begin{cases} 0,x \quad 2^n>x\geq 0\\ 2^n-x,0\geq x>-2^n\\ \end{cases} [x]={0,x2n>x02nx0x>2n
解释
正数比较好理解。负数需要稍微解释下。为什么是 2 n − x 2^n-x 2nx呢?
我们举个例子,具体体会下。比如-101这个二进制数将其表示为原码表示法。根据原码的含义我们直观可以写出1,101这个原码来。但是要用数学式子定义该怎么办呢?很容易想到把101加个负号(负负得正)然后再加上一个1000就可以了。 1 , 101 = 1000 − ( − 101 ) = 1 , 101 1,101=1000-(-101)=1,101 1,101=1000(101)=1,101把这个具体的例子推向一般化就可以得到上述的公式了。
注意要点
这个定义有个问题?就是0的原码表示有两个。如果把0作为正数(0固然不是正数,只是把0放到上面那个表达式里计算原码),那么0的原码就是 0 , 0 0,0 0,0,如果把0作为负数,那么0的原码就是 2 − 0 = 10 − 0 = 1 , 0 2-0=10-0=1,0 20=100=1,0。可见
[ 0 + ] 原 ≠ [ 0 − ] 原 [0_+]_原\neq[0_-]_原 [0+]=[0]

原码小数定义
[ x ] 原 = { x , 1 > x ≥ 0 1 − x , 0 ≥ x > − 1 [x]_原=\begin{cases} x,\quad 1>x\geq 0\\ 1-x, \quad 0 \geq x>-1\\ \end{cases} [x]={x,1>x01x,0x>1
解释
这里讨论的是纯小数。
小数方面我们是使用小数点来作为符号位和数值位的分隔符的。譬如 − 0.101 -0.101 0.101的原码表示就是 1.101 1.101 1.101请注意小数点前面的1表示的是符号的意思。
首先正数自然很好理解,不作解释。关于负数作少许解释,思想与正数类同。首先举例子: − 0.101 -0.101 0.101直观写出原码便是 1.101 1.101 1.101毋庸置疑。那么怎么用数学式子来求解呢?与上面相同我们考虑先将 − 0.101 -0.101 0.101添个符号让其变成正的,然后加1变得到结果咯。再将这个思想推广为一般方法就得到上述的式子了。
注意要点
我们还是要讨论下0的小数原码。
可以预见0的小数原码还是有两种。
当0取0.00时,正数的原码为 0.00 0.00 0.00,负数的为 1.00 1.00 1.00

总结
原码中: [ 0 + ] 原 ≠ [ 0 − ] 原 [0_+]_原\neq[0_-]_原 [0+]=[0]
0的表示有两个 0 − , 0 + 0_-,0_+ 0,0+。这也就产生了一定的浪费。

补码

补码的引入背景是很有意思的。我们可以从钟表中得到启示。因为太长,这里不做解释。一般的数电课本或者计算机组成原理课本上都会做引入解释,有兴趣的读者可以自行阅读。
补码整数表达式
[ x 补 ] = { 0 , x 2 n ≥ x ≥ 0 2 n + 1 + x 0 > x ≥ − 2 n ( m o d 2 n + 1 ) [x_补]=\begin{cases} 0,x \quad 2^n\geq x \geq0\\ 2^{n+1}+x \quad 0>x\geq-2^n(mod 2^{n+1}) \end{cases} [x]={0,x2nx02n+1+x0>x2n(mod2n+1)

解释
一般而言要得到一个负数的补码,只要用模去加上这个数就行了。
注意
1.这里的模是数值部分的位数n再加上1也就是n+1。为什么模要是 2 n + 1 2^{n+1} 2n+1而不是 2 n 2^n 2n呢?举个例子来解释。比如 − 101 -101 101如果用模3来求补码: [ − 101 ] 补 = 1000 − 101 = 0 , 011 [-101]_补=1000-101=0,011 [101]=1000101=0,011这样就和正数的补码产生冲突了。所以我们用模 2 n + 1 2^{n+1} 2n+1来求负数的补码。这个例子就是
[ − 101 ] 补 = 10000 − 101 = 1 , 011 [-101]_补=10000-101=1,011 [101]=10000101=1,011这样就符合了我们的理解了。

补码小数表达式
[ x ] 补 = { x 1 > x ≥ 0 2 + x 0 > x ≥ − 1 ( m o d 2 ) [x]_补=\begin{cases} x\quad 1>x\geq0\\ 2+x\quad 0>x\geq-1(mod2) \end{cases} [x]={x1>x02+x0>x1(mod2)
解释
负数可能比较难理解。为什么是 2 + x 2+x 2+x呢?
首先我们举个例子一个数值位有三位的小数x。
x m a x = 0.111 x_{max}=0.111 xmax=0.111与1差了0.001,但是我们直接用1去加的话就只能得到0.001这同样产生了冲突。所以要用2来加。

关于0的补码
我们以整数为例子。 [ − 0 ] 补 = 100 − 000 = 100 [-0]_补=100-000=100 [0]=100000=100舍去1也就是00。
[ + 0 ] 补 = 0 [+0]_补=0 [+0]=0
所以
[ − 0 ] 补 = [ + 0 ] 补 [-0]_补=[+0]_补 [0]=[+0]
这样补码就可以多表示一位负数。也就是上一篇文章(开头有上一篇链接)为什么int的表示范围,负数比整数多一个的原因了。

反码

反码就比较容易了。他就是把原码的每一位取反。这里也给出数学表达式,有了前面补码和原码的学习,反码的数学表达式易如反掌。
反码整数表达式
[ x ] 反 = { 0 , x 2 n > x ≥ 0 ( 2 n + 1 − 1 ) + x 0 ≥ x > − 2 n [x]_反=\begin{cases} 0,x\quad 2^n>x\geq0\\ (2^{n+1}-1)+x \quad 0\geq x>-2^n \end{cases} [x]={0,x2n>x0(2n+11)+x0x>2n
反码整数表达式

[ x ] 反 = { 0 , x 1 > x ≥ 0 ( 2 − 2 − n ) + x 0 ≥ x > − 1 ( m o d ( 2 − 2 − n ) ) [x]_反=\begin{cases} 0,x\quad 1>x\geq0\\ (2-2^{-n})+x \quad 0\geq x>-1 (mod(2-2^{-n})) \end{cases} [x]={0,x1>x0(22n)+x0x>1(mod(22n))

原码、补码、反码 转换方式 。

原码-补码
①每位取反 ②末位+1
不管是整数还是小数 原码到补码,补码到原码都可以这么算。读者可自行验算几个码。
原码-反码
每位取反,反之亦然。
补码-反码
末位减一,反之末位加一

你可能感兴趣的:(计算机组成原理,c)