二进制补码详解

二进制补码详解微处理器用二进制补码系统表示有符号整数 因为它可以将减法运算转换为对减数的补数的加法运算 详解如下

    微处理器用二进制补码系统表示有符号整数,因为它可以将减法运算转换为对减数的补数的加法运算。

1.什么是二进制补码运算

    我们先引入补数的概念:

补数:一个数与它的补数之和是一个常数。例如一个一位的十进制数与它的补数之和总是9,2的补数是7,4的补数是5。在n位的二进制算术中,数P的补数Q=2^{n}-Q(即常数是2^{n})。 

    令n位二进制数N的二进制补码定义为2^{n}-N。如果N=5=00000101(8位二进制数),则N的补码为2^{8}-00000101=100000000-00000101=11111011(注意此处11111011用于表示5的补码,不要看成无符号整数)。

    下面看几个例子:

5:00000101,5的补码:   

7:00000111,7的补码:

    例1:将7与5的补数相加

00000111 + =

    结果为9位二进制数。由于一共只有8位,我们忽略最左边一位,结果为00000010,也就是2。即7与5的补数相加结果为2,效果等同于7-5=2。

    例2:将7的补数与5相加

+00000101=

    结果为9位二进制数,忽略最左边第九位后结果为,“刚好”是二进制2的补码(2^{8}-00000010=11111110),也就是5-7=-2。

    从上述例子看,在二进制运算中,对于正数N而言,减去N的操作和加上N的补数的操作效果是相同的,也就是说-N等价于N的补数

    那么,为什么要引入补码运算呢? 

2.用补数的加法代替减法   

    二进制补码算术不是魔术,具体展开看,在n位的二进制算术运算中,我们令Z=X-Y,我们试着用X加上Y的补数来运算,由于Y的补数为2^{n}-Y,所以

X+Y的补数=X+(2^{n}-Y)=2^{n}+(X-Y)=2^{n}+Z

    换句话说,我们用X加上Y的补数会得到Z加上2^{n},但2^{n}只体现在最左边的第n+1位(如同上述例子中第九位的1),会被丢弃掉。所以此时我们得到了Z=X-Y=X+Y的补数,也就是说,在二进制补码运算中,减去一个数,等同于加上这个数的补码

    到这里,我们可以进一步直接放心地在二进制补码运算中用一个数的补码来表示这个数的负数了,如果不放心,我们还可以证明,对一个数进行两次求补将得到这个数本身:例如

-5=2^{8}-00000101=11111011

再次求补:-(-5)=2^{8}-11111011=00000101=5

    我们考虑加法的所有情况,请看下面的实例。令

X=9=0000101, -X=

Y=6=00000110, -Y=

    此时有

X+Y=00000101+00000110=00000111=15

X-Y=00001001+=100000011=3(红色最高位舍弃)

-X+Y=+00000110=1=-3(3的补码)

 -X-Y=+=1=-15(15的补码)

    结合之前所有的论证, 上述所有4中加减法中的情况都正确得到了我们想要的结果,例如将6与9的补码相加完成运算-9+6,得到-3,确实是3的补码。

3.求补运算

    我们现在可用补码加法来代替减法了,但是,例如N的补码是2^{n}-X,我们求补的操作本身不就是一次减法吗?!别急,补码运算可没这么蠢,求补的运算是非常简单的。我们将表达式2^{n}-X表示为下面的形式:

2^{2}-X={\color{Blue} 2^{n}-1}-X+1={\color{Blue} {1000...0}-1}-X+1={\color{Blue} 111...1}-X+1

    例如,8位(n=8)时有

2^{8}-X=100000000-X={\color{Blue} 100000000-1}-X+1 ={\color{Blue} 11111111}-X+1

    表达式111…1-X的值很容易计算。对于X的第i位n_{i},如果n_{i}=0,则1-0=1,同样,若n_{i}

=1,则1-1=0,很显然,取n_{i} 的反就行了,换句话说计算111…1-X部分的值只需要将X每一位取反。可见计算X的补码非常容易:

计算数N的补码,所要做的就是将X的每一位取反,然后将取反结果加1。

    例如,对于二进制的6=00000110,6的补码为+1=。

    这种补码运算相对于减法来说,非常适合用硬件实现,效率也很高。

4.补码的特点

  1. 补码是一个真正的互补系统+X+(-X)=0;
  2. 补码0被表示为00…0,是唯一的;
  3. 补码的最高位为符号位,如果符号位为0,则该数为正;符号位为1,则该数为负;
  4. n位二进制补码数的表示范围为(-2^{n-1})~​(2^{n-1}​​​​​​-1),例如对于n=8,补码的范围为-128~127.共有2^{8}=256个不同的数(128个负数,1个0,127个正数);
  5. 补码加法和减法可以使用同样的硬件完成,因为补码减法由被减数加上减数的补数实现。

 5.运算溢出

     n位二进制补码数的表示范围为 (-2^{n-1})~​(2^{n-1}​​​​​​-1)。如果运算结果位于这个范围之外会发生什么呢?

    我们令5位有符号二进制补码数的表示范围为-16~+15,考虑下面的例子:

    情形1:5+7=00101+00111=01100=12

    情形2:12+13=01100+01101=11001=-7

    在情形1中,我们得到了期望的结果+12,但在情形2中,我们得到的结果是一个负数,因为它的符号位是1,如果将他视作无符号整数,它将是2^{4}+2^{3}+2^{0}=25,但是我们不可能将两种解释应用到一个表示方法中,所以一旦采用了补码表示,那么11001就只能表示-7。

    同样,如果两个负数相加且结果小于-16,也会超出5位二进制补码的表示范围。

    情形3:-9-12=10111+10111=101011

    在情形3中,第六位1舍弃后,结果为正数01011=11。

    这两个例子都说明了什么是运算溢出,它发生在补码加法当两个正数的和为负数,或两个负数的和为正数的时候。也就是说,如果操作数A和操作数B的符号位相同,但结果的符号位与它们不同的时候,则可以判定发生了溢出。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/175932.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午11:04
下一篇 2026年3月26日 下午11:05


相关推荐

  • java常量表示_形参可以是常量吗

    java常量表示_形参可以是常量吗万千封印我知道编译器需要在编译时知道表达式才能编译一个开关,但是为什么foo.ba_常数不是呢?虽然从字段初始化后执行的任何代码的角度来看,它们都是常量,但它们不是编译时间常数在JLS所要求的意义上;见§15.28常量表达式的规格常数表达式1..这指的是§4.12.4最后变量它将“常量变量”定义为:我们称一个变量为原始类型或类型字符串,它是最终变量,并使用编译时常量表达式(§15.28)初始化为常…

    2026年4月18日
    8
  • linux配置jdk的环境变量(linux环境安装jdk)

    首先下载jdk在Linux中的安装包如rpm格式或tar.gz、tar.bz2格式(我用的是jdk-7u40-linux-i586.rpm即rpm格式)下载后进入Linux中jdk的下载目录然后安装jdk:rpm-ivhjdk-7u40-linux-i586.rpm如图:即安装成功此时查看java和javac命令的版本会出现如下情况java命令的版本和javac命令

    2022年4月17日
    99
  • 项目经理的职业化素养建设——石化干部管理学院培训「建议收藏」

    项目经理的职业化素养建设——石化干部管理学院培训「建议收藏」5月26日,应邀到中石化干部培训管理学院,给中石化海外新项目经理进行《项目经理职业化素养和核心能力建设》的培训。中石化干部培训管理学院坐落在北京立水桥畔,是中石化培训和培养干部的基地。参训的学员主要为中石化的海外项目经理,学员年龄在30-40岁之间,长期在海外工作,主管中石化海外项目管理,具有很强项目管理实践经验。本次培训定位在讲授“作为一个项目经理应该培养和建设什么样的职业化素养和和核心能力”,

    2022年10月16日
    5
  • thinkphp—display与fetch区别

    thinkphp—display与fetch区别

    2021年10月28日
    51
  • 迭代器iterator遍历集合

    迭代器iterator遍历集合集合分为 list set 和 map list 排列有序 可重复 set 排列无序 不可重复 map 键不可重复 值可重复 排列无序 一般遍历用 for 循环 但是 set 和 map 无序 所以要用迭代器 迭代器是将数据放在一个容器中 并排成一排 迭代器有一个游标 再未遍历之前 这个游标放在第一位元素的前面 一般是迭代器 iterator hasNext 判断游标后面是否有元素 iterator next 是将游标向后移一位 list 集合分为 ArrayList vector LinkedListAr 排列有序

    2026年3月18日
    2
  • 以太坊开发–geth的使用入门

    以太坊开发–geth的使用入门geth 的全称是 go ethereum 是一个以太坊客户端 用 go 语言编写 应该是目前最常用的客户端 当然以太坊客户端还有用 C Ruby Python Java 等其他多种语言编写的 不同类型的客户端是为了满足不同的需求场景 今天我们主要来介绍 geth 发音同 guess 的使用 nbsp nbsp nbsp 对于我们开发来说 比较普遍有两种方式打开 geth 控制台 以开发方式登录和私链方式登录 这两种方式是完全不

    2026年3月18日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号