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

先看一个例子:

为什么??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(符号位除外。

1000 0000 :1表示负数,000 0000取反 111 1111 加1:1000 0000 这个表示128  ,再加上符号位表示的负数,最后结果:-128.

 

那么怎么计算补码所表示的那个值呢?(答案:取反加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。

--------------------------------------1年后更新---------------

居然又忘了这个原码反码补码,碰到一个笔试题:

int a = 0xffffffff;

printf("%d",a);

结果为多少呢?

分析:0xffffffff (十六进制),即11111111  11111111 11111111 11111111(二进制)

补码:11111111 11111111 11111111 11111111

计算机直接把他当做补码处理啊,所以他是-1.

我还以为11111111是原码,计算机先把11111111转化成补码,再得其值。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值