二进制的减法原理解析

7/15/2022 3:53:44 PM
4278
0

这里需要说明的是,在计算机中做二进制数运算时,一定要明确是在多少位的整型前提下进行的,这样才能够正确处理位数溢出的问题。

其实减法也可以看成加法 6+(-4)

无论加减法总结:补码相加 结果再求补码

原码:我们将数字的二进制表示的最高位视为符号位,其中 0 表示正数,1 表示负数,其余位表示数字的值。
反码:正数的反码与其原码相同,负数的反码是对其原码除符号位外的所有位取反。
补码:正数的补码与其原码相同,负数的补码是在其反码的基础上加 1

在计算机中,负数是使用它的补码来表示的。所谓补码,就是反码+1。所谓反码,就是二进制数逐位取反。所谓逐位取反,就是1变成0,0变成1。例如:

原来的二进制数: 1011011101101反码: 0100100010010补码: 0100100010011

在数学里面,当我们判断一个正数和负数的时候,是通过这个数字前面的负号来判断的,例如: 5和 -5。但是由于计算机里面只有0和1,如何表示负号呢?因此可以使用一个额外的1来表示。例如:

正数: 0101负数: 1101

其中最左边的0和1表示的是符号位,0为正数,1为负数。

如果到这里,你以为你看懂了,那么我问你一个问题,下面几个数有什么区别:

0101

00101

000101

0000101

00000101

下面几个数有什么区别:

1101

10101

100101

1000101

10000101

实际上,他们表示的是不同位数条件下的同一个数。因为在计算机中,你定义一个数字的时候,是需要先提前指定这个数的类型的。例如int型、long型等等。(即便你用的Python,不需要人工指定,但是在底层它也会自动指定)。所以,如果我直接说:数字5在计算机中是怎么储存的,是没有意义的。应该说,数字5在8位整型下面是怎么储存的、在32位整型下面是怎么储存的:

00000101 # 8位整型

00000000000000000000000000000101 # 32位整型

所以,对于-5,在8位整型和32位整型下面,他们是这样储存的:

10000101 # 8位整型

10000000000000000000000000000101 # 32位整型

在计算机中,一个正数的补码就是它自身,例如 00000101的补码还是 00000101,而负数的补码,就需要根据补码的规则进行计算,例如在8位整型下,-5的补码运算规则如下:

1.首先计算正5的二进制数:00000101

2.逐位取反:11111010

3.加1:1111011

数字零的原码有 +0 和 −0 两种表示方式。这意味着数字零对应两个不同的二进制编码,这可能会带来歧义

在负零的反码基础上加 1 会产生进位,但 byte 类型的长度只有 8 位,因此溢出到第 9 位的 1 会被舍弃。也就是说,负零的补码为 00000000 ,与正零的补码相同。这意味着在补码表示中只存在一个零,正负零歧义从而得到解决。

接下来,例如我们在8位整型下,计算9-5的值,那么在计算机中,运算过程为:

1.求9的二进制补码(正数的补码就是它自身):00001001

2.求5的二进制补码:11111011

3.两个补码相加:100000100

4.由于我们是在8位整型的环境下,所以最左边这个1被直接丢掉了(溢出),结果变成:00000100

5.对结果再求补码。由于结果00000100最左边是0,表示正数,所以补码是自身。因此二进制数00000100对应的十进制数为4,就是正确结果。

 

再来看看8位整型条件下:10 - 13 = -3的过程:

1.计算10的二进制数补码:00001010

2.-13的二进制补码:11110011

3.两个补码相加:11111101

4.对结果求补码,由于最左边这一位是1,表示负数,所以要把十进制负数转二进制补码的过程反过来

5.先转成十进制正数对应的二进制数:00000011为3

6.把负号加上:-3,答案正确

这里需要说明的是,在计算机中做二进制数运算时,一定要明确是在多少位的整型前提下进行的,这样才能够正确处理位数溢出的问题。

由于位数溢出,在计算机中才会出现两个正数相加,结果却是负数的情况。例如:

127 + 1,在数学上结果为128,但是在计算机中,8位整型的情况下,结果为-128。原因如下:

1.计算127对应的二进制补码:01111111

2.计算1对应的二进制补码:00000001

3.两个补码相加:10000000

4.由于结果的最左侧为1,表示负数,因此要把十进制负数转二进制补码的过程反过来

5.先转成十进制正数对应的二进制补码:10000000(没错,10000000的补码恰好还是10000000)也就是128

6.加上负号:-128

 

所以说了这么多,依然很迷糊

补码到底是怎么回事,补码为什么要通过原码过度到反码再过渡到补码?

假设现在有一个表盘,并且时针指向两点,那么逆时针扳动三小时是几点呢,答案是十一点。
换种思路,我顺时针扳动9个小时,答案也是11点。

逆时针为3个小时,顺时针是9个小时,小时数加起来正好是12个小时,用小学时期学习的的角度的180度角类似的知识可以得到,3和9就是互补的。而这个12科学家称之为模。
 

比如:

9-2=9+8-10;

127-45=127+55-100;

1-99945=1+55-100000;

25-1=25-(100-99)=-100+25+99=25+99-100  

只要忽略进位,+99 就能代替-1。+99 就称为-1 的补数。

在这里用了 2 位 10 进制。
 

求补数的算法:补数 = 负数 + 10^2。

通用的公式是:补数 = 负数 + 10^n。 n 是位数。

计算机用二进制,补数,就改名为:补码。

一个字节,是 8 位 2 进制。计数范围是:0000 0000 ~ 1111 1111(十进制 255)。计数周期是:2^8 = 256。当满256时要进位:1 00000000,因为进位,所以256的二进制相等同于0的二进制

补码的定义式:负数的补码=负数+2^n。这个公司和是不是和10进制的非常相同

那么:

-1 的补码=-1 + 256 = 255 = 1111 1111。

-2 的补码=-2 + 256 = 254 = 1111 1110。

 

那么为什么要通过反码来求补码呢?

我们随便找一个256以内的数字(假设位数是8位)来举例-------   -15

15的二进制: 00001111

15的反码:11110000

将原码和反码相加刚好是 1111111=255    x相当于 10进制的(15+240)

我们知道 了  反码+原码=255 ,那么 反码+原码+1 是不是刚好溢出=0000 0000

所以 反码+1 就等同于  补码  了

 

 

给个例子

 

全部评论



提问