计算机为什么要用补码
目录
1. 补码诞生的背景
2. 原码、反码、补码
2.1 原码
2.2 反码
2.3 补码
3. 加减法
3.1 普通算术加减法
3.2 模N加减法
4. 总结
1. 补码诞生的背景
不论是在生活中还是虚拟网络中,人们总是习惯与10进制数字打交道,很容易理解10进制的加减乘除运算,但是我们知道计算机无法直接理解10进制,只能识别高低电平,一般人为设定0为低电平,1为高电平,所以又称计算机是二进制的。在计算机发展早期,人们要想使用计算机,只能使用计算机看懂的二进制与计算机打交道,如穿孔纸带,人们使用穿孔纸带将程序和数据转换为二进制码,带孔为1,无孔为0,计算机读取并处理完成后,同样在纸带上以二进制打孔输出计算结果,一般人很难操作这种早期计算机,只能是专业人士才能处理二进制的转换。随着科技的进步,普通人也能熟练的操作计算机,表面上似乎计算机已经理解了10进制,但是实际上,计算机最底层还是二进制的,这就需要10进制到二进制的自动转换以及使用二进制进行各种运算。
10进制到二进制的转换需要考虑两方面,第一个是编码格式,二进制中只有0和1,不同于常用的10进制使用 + 或者 - 符号代表正负数,要想让二进制只使用1和0代表正负数,需要找到合适的编码格式;第二个是运算,以加减运算为例,计算机内部是比较复杂的,计算机实现加法运算是很容易的,若直接作减法则比较复杂,需要处理借位等等,内部逻辑组件会增多,所以计算机一般在减去一个数的时候会转成加上这个被减数的负数,将减法转换成了加法,即A - B = A + (-B)。所以需要找到一种满足这两个方面的编码,目前10进制转换成二进制主要有三种方式:原码、反码、补码,下面将从编码格式和运算两方面对比这三种编码格式。
2. 原码、反码、补码
2.1 原码
原码是最简单也是最直观的从10进制到二进制的编码格式,人为规定原码的最高位为符号位,正数为0,负数为1,其余所有位为10进制数的绝对值。如下面例子:
10进制 | 二进制原码(4位) |
4 | 0 100 (首位为0,代表为正数) |
2 | 0 010 (首位为0,代表为正数) |
0 | 0 000 (首位为0,代表为正数) |
-2 | 1 010 (首位为1,代表为负数) |
-4 | 1 100 (首位为1,代表为负数) |
原码的优点是编码格式对人很友好,类似十进制中的正负号,原码用最高位0和1分别代码正负数,很直观的表示了正负数。但是原码也有一个很大的缺点,就是无法将减法转换成加法运算,如:
4 - 2 (10进制)= 4 + (-2)= 0 100 + 1 010 (二进制原码) = 1110 (二进制原码)= -6 (10进制)
上面例子计算4-2,将4-2转换成4+(-2)并用原码计算,得出的结果错误,原码虽然很直观转换了10进制数,但是计算输出的原码值并不正确,所以计算机不能直接使用原码存储和计算。
2.2 反码
反码的出现,主要是为了解决原码无法执行减法运算的问题,人为规定反码最高位为符号位,正数为0,负数为1,反码正数与原码正数格式一致,反码负数为负数绝对值的原码按位分别取反,如下面例子:
10进制 | 二进制原码(4位) | 二进制反码(4位) |
4 | 0 100 (首位为0,代表为正数) | 0 100 (首位为0,代表为正数) |
2 | 0 010 (首位为0,代表为正数) | 0 010 (首位为0,代表为正数) |
0 | 0 000 (首位为0,代表为正数) | 0 000 (首位为0,代表为正数) |
-2 | 1 010 (首位为1,代表为负数) | 1 101 (首位为1,代表为负数) |
-4 | 1 100 (首位为1,代表为负数) | 1 011 (首位为1,代表为负数) |
反码的负数编码格式不像原码那样直观,但是却可以将减法转换成加法了,反码减法规则为:A - B = A + (-B),如果最高位发生了溢位,则需要在最低位加上1,如下面两个例子:
1)4 - 2 (10进制)= 4 + (-2)= 0 100 + 1 101 (二进制反码) = 1 0001 (二进制反码,发生了溢位)= 0001 + 0001(最低位加1) = 0010 (二进制反码)= 2(10进制)
2)2 - 2 (10进制)= 2 + (-2)= 0 010 + 1 101 (二进制反码) = 1111 (二进制反码)= - 0 (10进制)
运用反码减法规则,得到的上面两个例子的减法结果是正确的,所以计算机是可以使用反码存储和计算的,早期的计算机如CDC 6000、LINC、PDP-1等都是使用反码的,但是反码也有两个缺点:1)0有两种编码,+0 (0000)和 -0 (1111),在判断0时,需要分别判断0000和1111;2)反码减法的算法规则比较复杂,需要增加计算机内部逻辑组件额外判断溢位,会影响计算效率。
2.3 补码
补码是现代计算机使用的编码格式,解决了上面反码的两个缺点。正数的补码与原码格式相同,负数的补码是将负数绝对值的原码分别按位取反,并加1,如下面例子
10进制 | 二进制原码(4位) | 二进制补码(4位) |
4 | 0 100 (首位为0,代表为正数) | 0 100 |
2 | 0 010 (首位为0,代表为正数) | 0 010 |
0 | 0 000 (首位为0,代表为正数) | 0 000 |
-2 | 1 010 (首位为1,代表为负数) | 1 110 |
-4 | 1 100 (首位为1,代表为负数) | 1 100 |
补码的减法规则比较简单,按照最简单的转换公式A-B = A + (-B),当减去一个数时直接转换成加上被减数的负数即可,不用像反码那样额外处理溢位,如下面两个例子:
1)4 - 2 (10进制)= 4 + (-2)= 0 100 + 1 110 (二进制补码) = 1 0010 (二进制补码,发生了溢位,直接丢弃溢位)= 0010(二进制补码) = 2(10进制)
2)2 - 2 (10进制)= 2 + (-2)= 0 010 + 1 110 (二进制补码) = 1 0000(二进制补码,发生了溢位,直接丢弃溢位)= 0000 (二进制补码) = 0(10进制)
使用了补码的加法,上面两个例子得出的结果都是正确的,相对于反码,补码加法更简单,直接丢弃溢位,不需要针对溢位单独处理,所以用补码做运算效率高。虽然补码运算过程很简单,但是转换和运算规则却很难理解,要弄明白其中的原理,就需要揭开补码背后的数学奥秘。
3. 加减法
加减运算有两种运算方式,一种是普通算术加减法,通常生活中使用的是10进制普通算术加减法;另一种是模N加减法,计算机补码执行加减运算,则是使用了模N加减法。
3.1 普通算术加减法
普通算术加减法是我们在生活中一直使用的,也是最简单和最容易理解的,通常人为使用 + 和 - 符号规定正负数,正数通常省略 + 符号, 如10,20,-10,-20,正负数的加减运算则可以看成是一维运算,如下图:
上图是普通算术加减法示意图,当执行加法运算时,需要向右移动,比如0+3,在0位置向右移动3位,即为0+3的结果;同样的,当执行减法运算,向左移动。向左和向右是没有尽头的,可以一直移动到正的无穷大或者负的无穷大。普通算术加减法简单直观,很容易被人理解,但是对于计算机要实现这样的算术加减法,既要区分正负数,又要分别实现加减法,设计就会很复杂,效率会很低,所以这套算术加减法并不适用计算机。所以需要找到一种不需要区分正负数就可以实现加减法转换的规则,那么计算机运行效率就会最高。
3.2 模N加减法
模N加减法正是不需要区分正负数就可以实现加减法转换的运算方式,不同于普通算术加减法,它是二维运算,要理解模N加减法比较困难,可以先用生活最典型的时钟举例,如下图:
上面是生活中常见的时钟,如果当前时间为凌晨1点,要知道5个小时之后的时间是多少,只需要顺时针旋转5格,指向了6点,即为1+5的结果;如果想知道5个小时之前的时间是多少,需要逆时针旋转5格,指向晚上8点,即为1-5的结果。时钟顺时针相当于时间向前走,逆时针相当于时间往后走,但是时钟不会指向无穷大的数,当转过24个小时(24小时制)又回到了原点。在时钟转动中,1-5的最终结果为晚上8点,逆时针旋转5个小时就可以得到正确结果,同时也可以顺时钟旋转19个小时(24-5,24小时制),两种方式旋转都最终指向了晚上8点。所以任意逆时针旋转得到的结果都能通过顺时钟旋转得到,当逆时针旋转N个小时,与顺时针旋转24-N小时相等,24又称为模,如果把顺时针看成是加法,逆时针看成是减法,那么时钟旋转可以看成模24的加减法运算,满足公式A-m=A+(24-m),即在时钟任一时刻A点,从A点逆时针旋转m个小时得到的结果,与从A点顺时针旋转24-m得到的结果一致。模N运算将减法转换成了加法。
计算机使用的二进制位数是有限制的,比如4位,8位,16位,64位等等,当数值太大超过最大位数时,会发生溢出,重新归0,所以计算机的二进制能表示的数不是无穷大的,由于溢出归零的特点,更像时钟旋转,如下图:
上图的四位二进制表示了从0000-1111,当超出1111时,四位已无法表示,会发生溢出,高于四位的位会被丢掉,比如1111加上2等于10001,10001包含五位二进制,最高位1会被丢掉,实际结果为0001,与时钟运算很相似,相当于在1111顺时针旋转了2个数。在时钟运算中,将顺时针看成加法,逆时针看成减法,那么时钟运算可以看成是模24的加减法,同理四位二进制也可以看成是模N的加减法,在4位二进制中,转一圈为2^4=16,所以4位二进制的加减法为模16的加减法,减法很容易的就被转换成了加法,即满足模N加减法公式:A-m=A+(16-m)。
虽然根据模N加减法实现了加减法转换,但此时又有新的问题,4位二进制只有1和0,是没有区分正负数的,而人们在计算的时候是要区分正负数的,所以需要人为将部分二进制划分为负数,另一部分划分为正数,根据模N加减法公式A-m=A+(16-m),当A为零点时,根据模N加减法公式得到 0-m=0+16-m,即-m=16-m,即将零点A逆时针移动m得到负数m,同时这个负数m也可以从零点A顺时针移动16-m得到,零点A可以为上面四位二进制任意一位,比如定义0000或者0001为零点都是可以的,但是为了简单运算,人为规定0000为零点,0000逆时针方向的为负数,顺时针方向的为正数。如在0000逆时针旋转1个数或者顺时针旋转16-1得到1111,那么1111代表-1,相应的顺时针移动一个数为+1,即用0001表示+1;同理在0000逆时针旋转2个数或者顺时针旋转16-2得到1110,那么1110代表-2,相应的顺时针移动两个数为+2,即用0010表示+2;同理1101和0011分别为-3和+3,1100和0100分别为-4和+4,1011和0101分别为-5和+5,1010和0110分别为-6和+6,1001和0111分别为-7和+7,但是1000比较特殊,0000逆时针旋转8个数得到1000,所以1000为-8,相应的顺时针旋转8个数也得到了1000,1000既能表示-8又能表示+8,为了不产生冲突,人为规定1000为-8。如下图:
上图中的四位二进制根据模N加减法划分出了正负数,同理对任意n位二进制,模N等于=2^n,根据上面的模N加减法公式得到-m = N - m = 2^n - m = (2^n -1) - m + 1,最终得到了负数推导公式-m = (2^n -1) - m + 1,(2^n-1)-m即为负数的原码绝对值按位取反,之后再加上1可以快速得到负数编码,又称这种负数编码为补码。补码负数范围转换成10进制为 -1 ~ -2^(n-1),正数范围转换成10进制为 0 ~ 2^(n-1)-1,所以补码转换成10进制为 -2^(n-1) ~ 2^(n-1)-1。
4. 总结
要想弄清楚补码,必须要弄清楚补码要解决的问题,计算机是二进制的,无法直接表示正负数,另外在计算机内部直接实现减法,也会影响计算机效率,所以人们希望要找到一种既能使用二进制表示10进制正负数的编码格式,同时这种编码格式又能满足将减法转换成加法进行运算,同时满足这两个条件有反码和补码,但由于反码中的0有两个编码格式,另外反码加法运算也比较复杂,慢慢地反码被淘汰了。补码刚好解决了反码的两个缺点,所以补码成了现代计算机的通用编码。
补码加减法运算不同于常规的算术加减法,补码使用了模N加减法,要想完全理解补码,首先要理解模N加减法。
计算机为什么要用补码相关推荐
- 计算机为什么要用补码?
人类在制造出晶体管后,利用晶体管制造出了与非门,然后又利用与非门制造出了加法器.加法器解决了加法运算问题.只有加法器是不够的,还需要解决减法的计算问题,但是与加法器相比,设计减法器硬件更为复杂,增加了 ...
- 验证:数据在计算机内存中以补码形式存储
#include<stdio.h> int main() {unsigned int a = -10;printf("%u", a); } 这个程序的输出是什么? 我们 ...
- 为什么计算机当中要采用补码
为什么用补码: (1) 为什么计算机中要使用补码? 在计算机的8位二进制表示法中,有原码.反码.补码三种方法.最高位均表示符号位,0+1-. 1.原码 正数 0 XXXXXXX 负数 1 XXXXXX ...
- 计算机中原码反码补码的应用场合,反码
反码是数值存储的一种,多应用于系统环境设置,如linux平台的目录和文件的默认权限的设置umask,就是使用反码原理.在计算机内,定点数有3种表示法:原码.反码和补码. 中文名 反码 外文名 Inve ...
- 源码 反码 补码详解(为什么计算机存储数值为补码形式?)
一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1.机器数 一个数在计算机中的二进制表示形式, 叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放 ...
- 深入理解计算机底层为什么采用补码运算【如何理解二进制计算高位溢出】
在计算机底层运算设计的过程中,是根据现实生活中的数学运算做出的映射.比如数学中的8-3=8+(-3),那么这样一来减法运算就变成了加法运算(你这时可能会问,我脑子直接计算8-3=5了,何必再转换位成加 ...
- 原码、补数、补码以及计算机中为什么用补码存储
原码:最左侧一位表示符号,且0表示正数,1表示负数:二进制转换为十进制时,符号位只用于取正负号,不参与转化. 例如1个字节的二进制: 0000 0001表示十进制的1: 0000 1010表示十进制的 ...
- java部分基础知识 (二):计算机组成原理 原码 补码 反码 按位符 移位符 按位与 按位或 按位抑或 非 分析hashMap的put方法原理
这里写目录标题 引言 符号位 正数的二进制计算 负数的二进制计算 按位符和移位符 按位符 移位符 分析hashMap运算符 byte和char 总结 引言 最近做完一个项目后,我忽然发现自己的基础并不 ...
- 计算机组成原理真值的补码,计算机组成原理:真值,原码,补码,反码,移码...
一,真值 就是现实中的数字(二进制)必须有+/-,实际中整数舍弃了+. eg:+1101010001 -1010001111 二,原码 计算机中唯一标识一个真值,但是不能用于计算以及无法实现减法,会产 ...
- 计算机组成原理:原码,补码,反码,移码
无符号数 寄存器的位数反映和决定无符号数的表示范围 比如八位的寄存器就只能储存十进制的0-255 有符号数 机器数与真值 在计算机当中没有硬件表示小数点的位置,而小数点的位置是我们自己约定的, 小数的 ...
最新文章
- 如何在全局程序集缓存 (GAC) 中安装 DLL 文件
- 在拦截器中获取请求参数,[Ljava.lang.String; cannot be cast to java.lang.String报错
- nginx反向代理编译异常
- kubernetes集群配置dns服务
- Universal-imageLoader缓存图片加载
- Android 使用Adapter适配器模式实现无线轮播BannerView
- 容器源码解析之HashMap(七)
- php运用like乱码,使用MySql和php出现中文乱码的解决方法
- 计算机网络7种类型,OSPF中7种类型LSA
- day18-事务与连接池 1.复习
- 2022年高压电工考试模拟100题及在线模拟考试
- 生成对抗网络GANs的用途
- C++ SHFileOperation实现文件、文件夹拷贝、删除、重命名
- 文本表示与文本特征提取的区别
- 敌兵布阵 HDU - 1166(树状数组-模板线段树写法)
- go语言能开发什么?go语言开发案例
- 计算机亮度快捷键,调节电脑亮度的快捷键是什么
- 使用清华镜像站下包、pip通过清华镜像站下载
- 减少代码重复率的方法
- VLAN特性 聚合、MUX VLAN、QinQ、映射