原码 反码 补码 详解
原码 反码 补码 详解
本篇文章讲解了计算机的原码,反码和补码.并且进行了深入探求了为何要
使用反码和补码,以及更进一步的论证了为何可以用反码,补码的加法计算原码
的减法.论证部分如有不对的地方请各位牛人帮忙指正~希望本文对大家学习计
算机基础有所帮助~
一.机器数和真值
在学习原码,反码和补码之前,需要先了解机器数和真值的概念.
1、机器数
数在计算机中的二进制
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示形式就称为机器数。机器数是带符号的,在计
算机用一个数的最高位存放符号(0 为正,1 为负),这样就将数的符号数值化了。
比如,十进制中的数+5,计算机字长为8bits,转换成二进制就是
00000101。如果是-5,就是10000101。
那么,这里的00000101 和10000101 就是机器数。
2、真值
因为符号占据一位,机器数的形式值就不等于真正的数值。例如上面的有
符号数10000101,其最高位1 代表负,其真正数值是-5 而不是形式值
133(10000101 转换成十进制等于133)。所以,为区别起见,带符号位的机器数
对应的真正数值称机器数的真值。
例:00100001 的真值=0 0100001=+33,10100011 的真值=1 0100011=– 35
二.原码,反码,补码的基础概念和计算方法.
在探求为何机器要使用补码之前,让我们先了解原码,反码和补码的概念.对
于一个数,计算机要使用一定的编码方式进行存储.原码,反码,补码是机器存储
一个具体数字的编码方式.
1.原码
原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值.比
如如果是8 位二进制:
[+1]原=0000 0001
[-1]原=1000 0001 第一位是符号位.因为第一位是符号位,所以8 位二进制
数的取值范围就是:
1111 1111--0111 1111 即-127--127
原码是人脑最容易理解和计算的表示方式.
2.反码
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上,符号位不变,其余各个位取反.
[+1]=[00000001]原=[00000001]反
[-1]=[10000001]原=[11111110]反可见如果一个反码表示的是负数,人脑无
法直观的看出来它的数值.通常要将其转换成原码再计算.
3.补码
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1.(即在
反码的基础上+1)
[+1]=[00000001]原=[00000001]反=[00000001]补
[-1]=[10000001]原=[11111110]反=[11111111]补对于负数,补码表示方式
也是人脑无法直观看出其数值的.通常也需要转换成原码在计算其数值.
三.为何要使用原码,反码和补码
在开始深入学习前,我的学习建议是先"死记硬背"上面的原码,反码和补码
的表示方式以及计算方法.
现在我们知道了计算机可以有三种编码方式表示一个数.对于正数因为三种
编码方式的结果都相同:
[+1]=[00000001]原=[00000001]反=[00000001]补所以不需要过多解释.但
是对于负数:
[-1]=[10000001]原=[11111110]反=[11111111]补可见原码,反码和补码是
完全不同的.既然原码才是被人直接计算的表示方式,为何还会有反码和补码呢?
首先,因为人脑可以知道第一位是符号位,在计算的时候我们会根据符号位,
选择对真值区域的加减.(真值的概念在本文最开头).但是对于计算机,加减乘数
已经是最基础的运算,要设计的尽量简单.计算机辨别"符号位"显然会让计算机
的基础
电路
模拟电路李宁答案12数字电路仿真实验电路与电子学第1章单片机复位电路图组合逻辑电路课后答案
设计变得十分复杂~于是人们相处了将符号位也参与运算的方法.另
外因为我们知道,根据运算法则减去一个整数等于加上一个负数,即:1-1=1+(-
1)=0,所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了.
为了是想上面的符号为参与运算,只保留加法的目的,首先来看原码:
计算十进制的表达式:1-1=0 1-1=1+(-1)=[00000001]原+[10000001]原
=[10000010]原=-2 如果用原码表示,让符号位也参与计算,显然对于减法来说,
结果是不正确的.这也就是为何计算机内部不适用原码表示一个数.
为了解决上面的问题,出现了反码:
计算十进制的表达式:1-1=0 1-1=1+(-1)=[0000 0001]原+[1000 0001]原
=[0000 0001]补+[1111 1110]补=[1111 1111]补=[1000 0000]原=-0 发现用反
码计算减法,结果的真值部分是正确的.而唯一的问题其实就出现在"0"这个特殊
的数值上.虽然人们理解上+0 和-0 是一样的,但是0 带有符号是没有任何意义的.
而且会有[0000 0000]原和[1000 0000]原两个编码表示0.
于是补码的出现,解决了0 的符号以及两个编码的问题:
1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[0000 0001]补+[1111 1111]
补=[0000 0000]补=[0000 0000]原这样0 用[0000 0000]表示,而以前出现问题
的-0 则不存在了.而且可以用[1000 0000]表示-128:
(-1)+(-127)=[1000 0001]原+[1111 1111]原=[1111 1111]补+[1000 0001]
补=[1000 0000]补-1-127 的结果应该是-128,在用补码运算的结果中,[1000
0000]补就是-128.但是注意因为实际上是使用以前的-0 的补码来表示-128,所
以-128 并没有原码和反码表示.(对-128 的补码表示[1000 0000]补算出来的原
码是[0000 0000]原,这是不正确的)
使用补码,不仅仅修复了0 的符号以及存在两个编码的问题,而且还能够多
表示一个最低数.这就是为什么8 位二进制,使用原码或反码表示的范围为[-
127,+127],而使用补码表示时的范围为[-128,127].
因为机器都是用补码表示数的.所以对于编程中常用到的int 类型,通常是
32 位(int32),则int 可以表示范围是:[231-1,231]因为第一位表示的是符号
位.而使用补码表示时又可以多保存一个最小值.
四原码,反码,补码再深入
计算机巧妙地把符号位参与运算,并且将减法变成了加法,背后蕴含了怎样
的数学原理呢?
将钟表想想成是一个1 位的12 进制数.如果当前时间是6 点,我希望将时间
设置成4 点,需要怎么做呢?我们可以:
1.往回拨2 个小时:6-2=4 2.往前拨10 个小时:(6+10)mod 12=4 3.往前
拨10+12=22 个小时:(6+22)mod 12=42,3 方法中的mod 是指取模操作,16 mod
12=4 即用16 除以12 后的余数是4.
所以钟表往回拨(减法)的结果可以用往前拨(加法)替代~
现在的焦点就落在了如何用一个正数,来替代一个负数.上面的例子我们能
感觉出来一些端倪,发现一些规律.但是数学是严谨的.不能靠感觉.
首先介绍一个数学中相关的概念:同余
同余的概念
两个整数a,b,若它们除以整数m 所得的余数相等,则称a,b 对于模m
同余
记作a?b(mod m)
读作a 与b 关于模m 同余。
举例说明:
4 mod 12=4 16 mod 12=4 28 mod 12=4 所以4,16,28 关于模12 同余.
负数取模
正数进行mod 运算是很简单的.但是负数呢?
下面是关于mod 运算的数学定义:
上面是截图,"取下界"符号找不到如何输入(word 中粘贴过来后乱码).下面
是使用"L"和"J"替换上图的"取下界"符号:
x mod y=x-y Lx/y J 上面公式的意思是:
x mod y 等于x 减去y 乘上x 与y 的商的下界.
以-3 mod 2 举例:
-3 mod 2
=-3-2xL-3/2 J
=-3-2xL-1.5J
=-3-2x(-2)
=-3+4=1 所以:
(-2)mod 12=12-2=10
(-4)mod 12=12-4=8
(-5)mod 12=12-5=7
开始证明
再回到时钟的问题上:
回拨2 小时=前拨10 小时
回拨4 小时=前拨8 小时
回拨5 小时=前拨7 小时注意,这里发现的规律~
结合上面学到的同余的概念.实际上:
(-2)mod 12=10 10 mod 12=10-2 与10 是同余的.
(-4)mod 12=8 8mod 12=8-4 与8 是同余的.
距离成功越来越近了.要实现用正数替代负数,只需要运用同余数的两个定
理:
反身性:
a?a(mod m)这个定理是很显而易见的.
线性运算定理:
如果a?b(mod m),c?d(mod m)那么:
(1)a?c?b?d(mod m)
(2)a*c?b*d(mod m)如果想看这个定理的证明,请看:所以:
7?7(mod 12)
(-2)?10(mod 12)
7-2?7+10(mod 12)现在我们为一个负数,找到了它的正数同余数.但是并不
是7-2=7+10,而是7-2?7+10(mod 12),即计算结果的余数相等.
接下来回到二进制的问题上,看一下:2-1=1 的问题.
2-1=2+(-1)=[0000 0010]原+[1000 0001]原=[0000 0010]反+[1111 1110]
反先到这一步,-1 的反码表示是 1111 1110.如果这里将[1111 1110]认为是原码,
则[1111 1110]原=-126,这里将符号位除去,即认为是126.
发现有如下规律:
(-1)mod 127=126 126 mod 127=126 即:
(-1)?126(mod 127)
2-1?2+126(mod 127)2-1 与2+126 的余数结果是相同的~而这个余数,正
式我们的期望的计算结果:2-1=1
所以说一个数的反码,实际上是这个数对于一个膜的同余数.而这个膜并不
是我们的二进制,而是所能表示的最大值~这就和钟表一样,转了一圈后总能找
到在可表示范围内的一个正确的数值~
而2+126 很显然相当于钟表转过了一轮,而因为符号位是参与计算的,正好
和溢出的最高位形成正确的运算结果.
既然反码可以将减法变成加法,那么现在计算机使用的补码呢?为什么在反
码的基础上加1,还能得到正确的结果?
2-1=2+(-1)=[0000 0010]原+[1000 0001]原=[0000 0010]补+[1111 1111]
补如果把[1111 1111]当成原码,去除符号位,则:
[0111 1111]原=127 其实,在反码的基础上+1,只是相当于增加了膜的值:
(-1)mod 128=127 127 mod 128=127 2-1?2+127(mod 128)此时,表盘相当
于每128 个刻度转一轮.所以用补码表示的运算结果最小值和最大值应该是[-
128,128].
但是由于0 的特殊情况,没有
办法
鲁班奖评选办法下载鲁班奖评选办法下载鲁班奖评选办法下载企业年金办法下载企业年金办法下载
表示128,所以补码的取值范围是[-
128,127]
本人一直不善于数学,所以如果文中有不对的地方请大家多多包含,多多指
点~