计算机为何对补码一见钟情

虽说早就接受到“原码”、‘’补码“、”反码“这些词,但始终不能确切体会到它们的真实用处。
这种感觉让人不爽,所以干脆查查资料,先给自己找个不错的原因做为思想的动力。

1.首先说说计算机为什么用二进制编码形式?

相信大家大致都清楚。这是德国数学家莱布尼茨提出的。
由于正好二进制里的0和1,正好和计算机内部用高低电平来表示数据的模式是对应的。
而且利用二进制,在开关开与闭,电压高与低的数据表示上不仅状态对应,而且很方便。
所以二进制就成了计算机的内部语言。

2.有了二进制,为何还要有十六进制,八进制,BCD码呢?
有十进制那是当然了,那是我们固有的思维,那当然不能丢了。现在系统位数都32或是64位了,
用二进制表示太冗长了,所以十六进制等才诞生了。个人认为有了十六进制,既能解决书写问题,
也能解决二进制与十进制的换算问题(虽说本来就能换算,但个人认为,二进制转成十六进制后,
再转十进制,固然方便些,反着也一样,不然长除法除2还不知道要除多少次呢)。可为什么还要
八进制,BCD码呢,人真是没事儿找事儿做吗?其实也不算了,有梨子就不要苹果了吗,只要有
营养,都栽种,我想后面两种码制就是为了增加转换途径吧,就像到达终点一样,多多少少还是要
有几个行走的途径吧,以不至于在一条路上把人给挤死。

3.数制转换
虽说简单,再次梳理熟能生巧。觉得熟悉的也可以认识认识几个单词,说不定你有不认识的单词。
再次留给大家脑袋中梳理,我也不一一赘述了。
decimal to binary: 整数部位除2取余,小数部位乘2取整            
 binary to decimal: 
decimal to octal:                
octal to decimal:
decimal to hexadecimal :        
hexadecimal to decimal:
4. 有这么多码制,为什么要用补码来存储数据呢?
查了网上的,就觉得有篇《闲扯原码反码补码》写得蛮好的,网址如下:
http://blog.csdn.net/ylqmf/article/details/5031788
不过个人还是觉得应该弄得再透一点,免得总是一回熟二回生的。
  (I)为什么不能用原码?

( 1 ) 10-  ( 1 )10 =  ( 1 )10 + ( -1 )10 =  ( 0 )10

(00000001) + (10000001) = (10000010) = ( -2 ) 显然不正确.
   通过上面原码计算式可以看出,当正数加上负数时,结果本应是正值,
得到的也有可能是负值(为什么是说有可能,其实就是被减数与减数相加数值超过0111 1111,
即127,就会进位,从而进位使符号位加1变为0了,这时结果就是正的了,
不过这时我又会想,符号位也要参与运算吗?待会儿我再解答),
而且数值部分还是被减数与减数的和,显然谬误。
例子:5-3=2;
 (0000 0101)原+(1000 0011)原=(1000 1000),即-8,明显不符。
当负数加上负数时(这里就拿两个数值部分加起来不超过0111 1111的来说),我们可以明显
看出符号位相加变为0,进位1被溢出。结果就是正数了,更是让人吃惊。
因此原码毫无疑问的被排除了。

符号位参不参与运算?
上面我都用到了一个假设,就是符号位参与运算。
我第一反应就是计算机会不会对符号位特殊对待呢?想了一会儿,证明自己还是很愚蠢的。
例子:5-3=2;
(0000 0101)补+(1111 1101)补=(1 0000 0010),溢出的1除掉,结果就是正数2.
上面补码运算中我们云算了符号位,若是算符号位,那结果符号位又该是什么呢?我们知道
是正的,但计算机毕竟不是人的头脑,它就难从0 和1里抉择了,所以说,计算机对待每一位
都是公平的。我是不是很愚蠢啊。

(II)为什么不能是反码?
 针对这点,我觉得上面博客里说不过去,向来特殊不能说明一般的。
我喜欢从例子中看出名堂,下面说说一例。
例子:-8-3=-11,
    (1111 0111)反+(1111 1100)反=(1111 0011),再求其反码,可得是1000 1100,即-12
为什么结果就小了一个1呢?我想到反码加1就是补码,其间一定有什么不可告人的秘密呵呵。
  下面我就用十进制思维思考了:
       1111 0111数值部分为119,即(127-8),1111 1100数值部分为124,即(127-3),
本来119+124=243,超过了127,进了一位加到符号位上去了,于是结果为243-128=115,
    正是1111 0011 的数值部分。然后127-115,就是12呢,结果就是这样来的。
你看出其中的破绽没?
      也许我把你给绕晕了吧。我们假定上面的127为X,
    则根据上面流程,结果数值部分就为x-[ (x-A)+(x-B)-(x+1)],
这里A、B都是指数值部分,结果化简就是A+B+1.本来两个小负数相加,是A+B,现在却大了1,
再添个负号,自然算出的结果比正常结果小了1 了。这下明白了吧。
   问题就出在(x+1)身上,本来总共表示的最大数值部分是127,你却一下子就减掉128(这就默认了
最大数值应该存在128,可事实不存在),就像一块土地只有一寸大,你却想在其上建个占地面积两寸的房子,
显然不符合常理。因此反码也瘪下去了。

(III)那又为什么最后落到了补码身上了呢?
        如果是数学题,而且只有这三种码,我的目的就已经达到了。不过我还是想看看补码到底怎么就行得通的呢。
   其实知道反码和补码就是因为一个1的差别,到底怎么弥补呢?
       要想建两占地寸的房,就得把地开荒到两寸。因此某某就把非分之想施加到‘0’的身上了。
    无中生有的把0分为正0和负0,然后负0变成-128,这样数值范围就增加了1,这样就和上面运算吻合了。
   现在无非是这些特殊数的各种码表示问题。

下摘自于http://tieba.baidu.com/f?kz=1069352613,相信对你也很有启发。
  我们都知道,数值在内存里都是以补码形式存储的。正数的原反补都一样,负数的补码等于原码的反码加1.
但对于0来说,它有符号位吗?     

以一个8位的系统来说,有符号数的二进制为(1000 0000),表示的是-0,还是-128呢?
  
看看负数补码的公式:负数的补码=1 0000 0000(模)- 数的绝对值   
比如:-1: 1111 1111 =1 0000 0000 - 0000 0001     
   -2: 1111 1110 =1 0000 0000 - 0000 0010     

假设1:表示-0。     
那么 -0的补码: 1 0000 0000 - 0 =0000 0000,和+0一样。    
反码: 1111 1111 (0000 0000 -1 = 0000 0000 +1111 1111=1111 1111)    
原码: 1000 0000(反码取反)

假设2:表示-128。   
-128的补码: 1 0000 0000 - 1000 0000(+128没有符号位)= 1000 0000     
   反码: 1111 1111 (1000 0000 -1 =1 000 0000 + 1111 1111 = 1111 1111)(补码-1) 
   原码: 1000 0000(反码取反)
   从上面看来,一个原码对应了2个补码。按照C语言的定义,在32位的系统里,int表示的范围为-2^31 ~ +(2^31-1),那么可以推论出有符号数可以表示负的最大值,而没有-0的定义。也就是说上面1000 0000 表示的应该是-128,而不是-0。

      关于运算,虽说简单,但要想确确实实知道计算机怎么处理的,还是很让人有动力的。
        下篇打算想想补码如何在运算过程中大显神通的,欢迎来访。    

     

     







  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值