先看一个例子:

探究整数编码原理。深入理解原码、反码和补码。

为什么??c = (-100)+(-100的),打印出来的结果为56呢??

让我们探究整数的编码之旅吧!

一.各种概念各种定义···

1.无符号整数,例如unsigned char/int/short 就不介绍了。

2.有符号数 char/int的编码:

(1)原码:原码表示法是整数的一种简单表示法。符号位:0表示正号,1表示负。数值一般用二进制表示。

(2)反码:正数:其反码和原码相同。负数:其反码为原码各位取反而得到(但是符号位除外)。

(3)补码:正数:其补码和原码相同。负数:其反码为其反码的基础上末位加1;即:取反加1。

但是但是!为什么!为什么要设计原码反码补码?有啥子用?考试吗?(恩,大一的时候作为初学者,在考试时总会想这个问题,啊这是为什么这这样设计?)。

直到看到了下面这句话:

所有编码系统的设计,都在追求连续性和唯一性。原码、反码和补码的演化,就是在不断提高整数编码的这两个方面。

重点是:连续性!唯一性!


二.图形解读整数编码:

1.原码的二进制码与整数对用的关系图:

探究整数编码原理。深入理解原码、反码和补码。

上图发现两个bug:

(1)存在重复0,分别0000 0000 和1000 0000

(2)存在两个间断点,分别为:

0111 1111 -> 1000 0000,即127突变为-0.

1111 1111 -> 0000 0000,即-127突变为+0.

这就涉及到整个整数范围内的数值连续性,任何的间断点都会导致溢出问题。所以间断点越少越好。


2.反码的二进制码与整数对用的关系图

探究整数编码原理。深入理解原码、反码和补码。

观察图一图二,发现右边图形做了一次翻转,bug2的间断点被修复了,也就是说间断点从两个变成一个。

bug1:依旧存在重复0。

bug2:两个间断点减少到一个,不能再优化了。


3.补码的二进制码与整数对用的关系图

探究整数编码原理。深入理解原码、反码和补码。


再观察,我们发现这一次右边图形向下移动1,于是最小负整数从-127变成-128.


char:一个字节 8位(1,2,3·····127,-128,-127,·····2,1,0,1,2循环下去···)

原码:最大值 0111 1111(0符号位表示正 十进制表示为127)如图一

          最小值1111 1111(1符号位表示负 十进制数为-127)如图一

结合图示,也就是说,原码本来是有bug的,它不准确,所以计算机中不用原码来计算。

补码:最大值0111 1111(127)如图三

         最小值10000 000(-128)如图三

这里我纠结了一下为什么补码1000 0000表示为-128而不是-0。说明还是有点懵啊。

因为它是补码,是补码!是补码!通过三张图也看的出来,补码是经过优化的,补码 = 原码取反+1(符号位纯爱),所以补码没有bug了!! 


那么怎么计算补码所表示的那个值呢?(答案:取反加1包括符号位)

例如:补码1000 0001,求其表示的十进制值  分3步:

1.它是补码 所以1为符号位,十进制是一个负数。

2.取反后为0111 1110;再加1为0111 1111表示127

3.最后得结果:-127

总结:补码计算其表达的数值(十进制)的时候,取反,加1,包括符号位。

这里容易与“补码 = 原码取反加1,符号位除外”记混淆,所以我们再看一个例子:

-10(十进制),原码为:1000 1010(有负,第一位为1,10的二进制为1010),

补码为:1111 0110(原码取反加1 && 符号位除外)

通过补码算原本的值:1.它是补码并且第一位1,所以得出:负数。2.取反0000 1001,加1:0000 1010 3.得出:-10 


所以,为什么要有补码,因为一开始只有原码,但是原码有bug,怎么办,那就优化一下(取了个反加了个1),然后给它起了个名字,叫:补码。

再通过下面例子观察原码反码补码的差别:

探究整数编码原理。深入理解原码、反码和补码。

通过这个例子,我们发现,好神奇,只有补码没有计算错误。


最后,回到最初的问题,c = (-100)+(-100)

计算机中,存储有符号char以补码形式。

-100的原码为:1110 0100(第一位1表示负 110 0100表示100)

-100的补码为:1001 1100

两个(-100)相加,形式为两个补码相加:

1001 1100 + 1001 1100 = 0011 1000

补码0011 1000第一位为0,说明是正数,再算其值为:56。


相关文章: