原码、反码、补码介绍(主要补码)

1.为什么用补码

首先肯定一点,计算机中非浮点数(浮点数没研究过)都是用补码表示二进制数的,为什么用补码而不用原码或者反码,是因为补码系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。减法电路得设计相对而言更复杂。

2. 为什么补码可以实现减法

要想理解这一点,首先必须知道同余的概念。想象一个时钟,如下图

现在是8点钟,如果我想时间变到6点中,那么我有两种方法,第一种顺时针10个小时,第二种逆时针旋转2个小时,都可以得到6点钟。但是就本质而言,这两种方法得到的6点钟,其实是不同的。如果8点是上午8点,那么第一钟方法得到的其实是下午的6点,但第二钟方法得到的是上午的6点。但是对于这个表而言,它只有1点到12点,并没有上午下午之分,对于它而言,这两张方法得到的都是6点钟(时钟指针都是指向6),并没有区别。

换成计算的方式,第一中方式相当于8+10=18\equiv 6,第二种方式相当于8-2=6。

在这个时钟的例子里,一个时钟最多只能表示12个小时,即从1点到12点。上例中的8点加十个小时,计算结果是18时,但是时钟最多只能表示12时,这种情况下就是溢出了,超出了时钟能表示的范围,最后结果是6点。

那么在这种情况情况下的加减运算都是模12的加减运算,12就是时钟能表示的数字范围。而同余表示两个数除以12,余数相同,称之为同余,用\equiv 表示。这个概念以及符号最早是高斯提出来的,果然是个伟人。

3.补码的计算

当你查阅资料时,尤其是用百度(程序员还是用google好),你会发现大部分人写的补码的计算方法都是:符号位不变,其他位取反,末位加1。也就是说要算补码,先拿到反码。这里补充一下原码、反码、补码的知识。原码就是二进制数,比如2,用8位二进制就是0000 0010,那反码就是加入符号位(0表示正数,1表示复数),最高位表示符号位,比如-2,用8位二进制就是1000 0010,最后补码,比如-2,就是-2的符号位不变,其他位组为取反,即1111 1101,然后末位加1,即1111 1110。正数的原码反码补码相等,都是原码。

但是如果你感兴趣,自己琢磨,你会发现有个特殊的数字0,按照上述的方法计算会纠结,0的原码是0000 0000,反码是1000 0000,如果除符号位逐位取反,即1111 1111,再加1的话,会产生进位,这个进位,要不要进给符号位,如果给,那就是0000 0000,如果不给,那这个进位浪费掉,最后是1000,0000。而实际的结果是多少呢,是0000 0000,符号位参与运算。而也就是说0的补码还是0。而这个1000 0000其实也是有特殊用途的(后面说)。在整个补码的计算过程中,只有计算0的补码会产生溢出。

上面说了0计算的补码还是0,其实还有一个特殊的补码,即1000 0000,这个补码,你找不到原码,不信你找找看。

其实如果你想得多,你会发现这两个特殊的数。就拿8位的二进制来说,能表示256个数。如果按照上述说的补码来表示的话,正数能表示0-127,刚好128个数,256的一半,那么负数必然也能表示另外一半,难道是(-0)-(-127)?很明显,-0是没有的,因为0的补码还是0,那么(-1)-(-127)只有127个数,剩下一个是什么?就是那个无法计算补码的数1000 0000。既然(-0)没意义,那么这个多出来的数就表示-128,这样刚好不浪费。(补一句,如果用反码表示,那还真的有-0,等于浪费一个数)。这个现象如果你写代码一定能发现,比如java的int类型或者long类型,最小负数的绝对值一定比最大正数大1,不信你试试看。

上述的计算补码的方式其实说复杂了,简单的方法是直接逐位取反,末位加1即可。而且这个反过来也可以,即知道补码求原码,也能这样算。

补码的计算为什么是逐位取反,末位加1,拿8位二进制举例,其最大能表示2^8 =256个数,那么一个数逐位取反后,这个取反后的数和原数相加必定等于257,比如1001 0010,逐位取反后,是0110 1101,这两个数相加一定是1111 1111,即257,再加上1,就是258。所以一个数的补码的计算可以概括为一下公式,如果一个数是a,二进制位数是n,那么补码就是2^n -a。

现在,如果你已知一个补码b,让你求原码,你怎么计算,按照逐位取反,末位加1的反向计算可不可以,当然可以,先减一,再逐位取反(符号位不变)。但是如果你将上面的那段推理看明白的话,其实同样按照逐位取反,末尾加1的计算方式即可。(回头看看那个无法求原码的补码1000 0000,按照逐位取反,末位加1,得到的还是1000 0000)

这个模型就是a+b=2^n ,那么a=2^n-b,b=2^n-a。

4 补码的同余

对于一般的计算,a的补码我们认为是-a,为什么可以这样。对于a,根据计算公式,其补码为2^n -a,我们需要认定的是-a与2^n -a同余即可。

-a=-a-(2^n *(-1))...2^n -a,即商取-1,得到余数是2^n -a

对于2^n -a,商取0即可,得到余数是自身,与-a的余数相同,得到 -a\equiv 2^n -a

从而用这种方式计算补码,表示负数。(对于负数取余,各个语言有些差异,主要在取商上面,请看参考文档)

以上,我们得出结论,a的补码即为-a

5 运算

补码只是解决两数相减的运算,对于两正数相加,两负数相减的溢出问题,任然还是问题。也就是说溢出了,就超出了能计算的范围,答案就是错的。

观察一下补码的运算,一个正数减去另一个正数,或者说一个正数加上一个负数。对于补码,以8位举例,最大的数-1,是1111 1111,最小的数-128,是1000 0000,我们看,最大的数是最容易溢出,溢出后表示的就是正数,而计算结果也正是正数。而最小的数反而是最不容易溢出的,那相加的数没溢出,表示的数还是负数。

6 番外

注意,8位二进制能表示256个数是没有质疑的,但是能表示哪256个数,却是人为定义的。

比如负数,表示(-1)-(-128)很容易理解,但是,根据上面的同余概念,(-1)与(-257)同余,

(-128)与(-384)同余。那么,负数部分表示(-257)-(-384)可不可以?当然可以,但是

正数部分表示的数也得相应改变(由(0)-(127)变为(256)-(383)),这样才能保证计算结果结果正确。

参考资料:

https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%A3%9C%E6%95%B8

http://ceeji.net/blog/mod-in-real/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,200评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,526评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,321评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,601评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,446评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,345评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,753评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,405评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,712评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,743评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,529评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,369评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,770评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,026评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,301评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,732评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,927评论 2 336