您的位置:首页 > 其它

关于原码、反码和补码的故事

2016-01-29 18:06 549 查看


在学习之前,我们来看一个问题,在C/C++中,为什么char型的范围是-128~127,int型的范围是-2147483648~2147483647,为什么负数的绝对值比正数的绝对值要大1???要解答这个问题,就要明白原码、反码和补码的产生过程。

下面我们将-1和1三码的表示方式如下,

原码:0000 0001

反码:0000 0001

补码:0000 0001

以上是1的三码,可以看到,三者是一个样子的。

再来看-1

原码:1000 0001

反码:1111 1110

补码:1111 1111

 

原码就是最原始的机器码,最高位代表符号位,余下的位代表数值位,没啥好说的。

反码是在原码的基础上,符号位不变,数值位置反

补码是在反码的基础上在加1。

三者的概念明白了我们再来看为什么会有这样一个问题,既然有了原码,那还要反码和补码干啥?(如果你以前没有这个疑问,  那么你现在可以有了~~~)?

A:是啊,有了原码不就够了吗!?、

B:答案是不够!

A:为啥?

B:请你用原码计算一下1-1

A:很好计算啊,因为计算机不支持减法,只支持加法,所以1-1要转换成1+(-1)来计算(得意的笑~~~)

B:说的对,那请你用原码算一下,

A:So easy!

下面是A的计算过程:

1的原码:0000 0001

-1的原码:1000 0001

两者相加

0000 0001

+

   1000 0001

--------------------------------

   1000 0010

哎呦我擦,1-1的结果是-2!!!

A的世界观瞬间崩塌,何解??!!

看来原码直接计算是不行的

怎么办呢,于是乎计算机科学家想出了用反码参与计算(也许并不存在反码,所谓的反码这是计算机科学家在设计计算方式的过程中产生的副产品,在实际计算机中毫无用处,反而在教科书中成了在讲解由原码到补码转换过程中的中间变量,然而这个反码反而使得讲解更加的麻烦了,当然,这只是作为一个男人的直觉而已,你懂得),用反码计算的过程如下

0000 0001

+

1111 1110

----------------------------

1111 1111

1111 1111是反码,我们还原成原码来解读数值,原码是1000
0000,这是个什么鬼??!!-0???虽然是0,但是怎么是个负0呢,0难道还有正负(也许将来数学体系从根本上变了呢,也许会有吧),我们期待的结果不应是0000
0000这个0吗,怎么出现个山寨的1000 0000这个-0呢,计算机科学家不开心,于是乎继续创造,终于,终极Boss补码驾到!!!

1的补码:0000 0001

-1的补码:1111 1111(是不是终于明白在C/C++编程时,有时给一个int型赋值-1时要写成a=0xFFFFFFFF了呢)

用补码来计算1-1如下

0000 0001

+

1111 1111

---------------------------

  10000 0000

得出来个9 bit的结果,没事,我们知道在计算机中,有溢出这个概念,最高位那个1直接扔了就是了,最后结果就是0000
0000,这才是我们想要的结果嘛!!!

But,我们文章开端最初的问题貌似还没有解答,为什么char型的范围是-128~127呢???如果细心,你会发现,就是那个山寨的-0(1000
0000)我们还没有处置呢,咋办呢?这时科学家已经绞尽脑汁费死了劲才解决了1-1这个问题,不想再为这个山寨的-0费脑子了,那么1000
0000这个数在无符号类型的原码中表示的是128,那么在有符号的类型中就表示-128吧,嗯,就这样吧,又不碍事~~~

完美解决!

总结:

反码只是个跑龙套的,在计算机中没有反码的概念,更具体说是并没有实际用到反码。

补码才是计算机中真正参与计算的编码方式。

至于-128~127中的-128并没有特殊意义,之所以是在机器中的原码是1000 0000是因为在有符号类型中1000
0000应该是负0,但是不能有个0还要个负0,因此负0就成了-128了。(完全属于个人腹黑!!!,至于真正的原因,其实我也不知道-_-!!!)

以上只是个人根据网络上的一些见解和自己的理解总结的,至于那些原来的帖子的出处实在找不到了。

如果阐述有误,请指出,不要误了更多人,多谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  原码 反码 补码