计算机进制转换
我们总是说八位二进制表示的数的范围是:-128——127,
可是我们知道在八位二进制原码【(-127~-0 +0~127)共256个】,反码【(-127~-0 +0~127)共256个】,都没有表示到-128,而为什么说八位二进制数的表示范围就是-128——127呢,其实在于补码!补码的表示范围是【(-128~0~127)共256个】,所几进制所表示的范围是尤其补码来确定的。比如说,十进制-128在八位二进制原码中表示不了,八位二进制反码中表示不了,而八位二进制补码中可以表示,那么就可是说十进制-128是可以表示的,可以用八位二进制来表示的,所以其范围就有了-128,终期八位二进制范围就是:-128——127.
八位二进制数为什么表示的范围是: -128 —— +127?
计算机对有符号数(包括浮点数)的表示有三种方法:原码、反码和补码
8位原码能够表示数的范围是 -127~127
8位反码能够表示数的范围是 -127~127
8位补码能够表示数的范围是 -128~127
既然范围是-128~127,那肯定是用补码表示的。
下面摘抄网上的一些讲解,觉得蛮不错的。
原码:最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。
反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。
补码:正数的补码与其原码相同;负数的补码是在其反码的末位加1。
1、原码、反码和补码的表示方法
(1)原码:在数值前直接加一符号位的表示法。
例如:符号位 数值位
[+7]原= 0000 0111B
[-7]原=1000 0111B
留意:a. 数0的原码有两种形式:
[+0]原=00000000B [-0]原=10000000B
b. 8位二进制原码的表示范围:-127~+127
(2)反码:
正数:正数的反码与原码相同。
负数:负数的反码,符号位为“1”,数值部分按位取反。
例如:符号位 数值位
[+7]反= 0000 0111B
[-7]反=1111 1000B
留意:a. 数0的反码也有两种形式,即
[+0]反=00000000B
[- 0]反=11111111B
b. 8位二进制反码的表示范围:-127~+127
(3)补码
2)补码的表示:
正数:正数的补码和原码相同。
负数:负数的补码则是符号位为“1”,数值部分按位取反后再在末位(最低位)加1。也就是“反码+1”。
例如:符号位 数值位
[+7]补=0000 0111B
[-7]补=1111 1001B
补码在微型机中是一种重要的编码形式,请留意:
a.采用补码后,可以方便地将减法运算转化成加法运算,运算过程得到简化。正数的补码即是它所表示的数的真值,而负数的补码的数值部份却不是它所表示的数的真值。采用补码进行运算,所得结果仍为补码。
b.与原码、反码不同,数值0的补码只有一个,即[0]补=00000000B。
c.若字长为8位,则补码所表示的范围为-128~+127;进行补码运算时,应留意所得结果不应超过补码所能表示数的范围。
2.原码、反码和补码之间的转换
由于正数的原码、补码、反码表示方法均相同,不需转换。
在此,仅以负数情况分析。
(1已知原码,求补码。
例:已知某数X的原码为10110100B,试求X的补码和反码。
解:由[X]原=10110100B知,X为负数。求其反码时,符号位不变,数值部分按位求反;求其补码时,再在其反码的末位加1。
1011 0100原码
1100 1011 反码,符号位不变,数值位取反
1+1
1100 1100 补码
故:[X]补=11001100B,[X]反=11001011B。
(2)已知补码,求原码。
分析:按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1 有方法。
例:已知某数X的补码11101110B,试求其原码。
解:由[X]补=11101110B知,X为负数。求其原码表示时,符号位不变,数值部分按位求反,再在末位加1。
1110 1110补码
1001 0001 符号位不变,数值位取反
1+1
1001 0010 原码
1.3.2有符号数运算时的溢出题目
请大家来做两个题目:
1)(+72)+(+98)=?
0 1 0 0 1 0 0 0 B +72
+ 0 1 1 0 0 0 1 0 B +98
1 0 1 0 1 0 1 0 B -42
2)(-83)+(-80) = ?
1 0 1 0 1 1 0 1 B -83
+1 0 1 1 0 0 0 0 B -80
0 1 0 1 1 1 0 1 B +93
思考:这两个题目,按照正常的法则来运算,但结果显然不正确,这是怎么回事呢?
答案:这是由于发生了溢出。
几点注意的地方:
<1>计算机里无论什么进制数都是以补码表示的!
<2>原码中:+0(00000000B) -0(10000000B)
反码中:+0(00000000B) -0(11111111B)
补码中:(00000000B) -128(10000000B)
<3> 如何通过原码、反码、补码当前数字来得出原数字的大小:
正数:直接计算出当前数字,就是原数字
原码:
负数:直接计算出当前数字,就是原数字
正数:直接计算出当前数字,就是原数字
反码:
负数:当前数字+所求原数字=-127
正数:直接计算出当前数字,就是原数字
补码:
负数:当前数字+所求原数字=-128
<4>用补码表示的数,参加加法、减法(当然都转为为加法运算)乘法、除法运算时,即在做加法运算时,满二进一位,但请注意,采用补码进行运算,所得结果仍为补码。
<5>已知补码,求原码。
分析:按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1的方法。
例:已知某数X的补码11101110B,试求其原码。
解:由[X]补=11101110B知,X为负数。求其原码表示时,符号位不变,数值部分按位求反,再在末位加1。
1 1 1 0 1 1 1 0 补码
1 0 0 1 0 0 0 1 符号位不变,数值位取反
1 +1
1 0 0 1 0 0 1 0 原码
参考资料:
网址:
http://blog.csdn.net/csw_100/article/details/5844751
数值在计算机中表示形式为机器数,计算机只能识别0和1,使用的是二进制,而在日常生活中人们使用的是十进制,”正如亚里士多德早就指出的那样,今天十进制的广泛采用,只不过我们绝大多数人生来具有10个手指头这个解剖学事实的结果.尽管在历史上手指计数(5,10进制)的实践要比二或三进制计数出现的晚.”(摘自<<数学发展史>>有空大家可以看看哦~,很有意思的).为了能方便的与二进制转换,就使用了十六进制(2
4)和八进制(23).下面进入正题.
数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).这就是机器数的原码了.假设机器能处理的位数为8.即字长为1Byte,原码能表示数值的范围为
(-127~-0 +0~127)共256个.
有了数值的表示方法就可以对数进行算术运算.但是很快就发现用带符号位的原码进行乘除运算时结果正确,而在加减运算的时候就出现了问题:
( 1 ) 10- ( 1 )10 = ( 1 )10 + ( -1 )10 = ( 0 )10
(00000001)原 + (10000001)原 = (10000010)原 = ( -2 ) 显然不正确.
因为在两个正整数的加法运算中是没有问题的,于是就发现问题出现在带符号位的负整数身上,于是引出了反码(对于正整数原码、反码是一样的,而负整数的反码是原码除最高位(符号位)外其余所有位的逐位求反。).反码的取值空间和原码相同且一一对应. 下面是反码的减法运算:
( 1 )10 – ( 1 ) 10= ( 1 ) 10+ ( -1 ) 10= ( 0 )10
(00000001) 反+ (11111110)反 = (11111111)反 = ( -127) 反= ( -0) 还有问题?!
( 1 )10 – ( 2)10 = ( 1 )10 + ( -2 )10 = ( -1 )10
(00000001) 反+ (11111101)反 = (11111110)反 = ( -126) 反 =( -1 ) 正确
问题出现在(+0)和(-0)上,在人们的计算概念中零是没有正负之分的.(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大).
于是又引入了补码(用最高位表示符号位,如果是0表示正数,如果是1表示负数,剩下的7位用来储存数的绝对值的话,能表示128个数的绝对值,再考虑正负两种情况,128*2还是256个数。首先定义0在计算机中储存为00000000,对于正数我们依然可以像无符号数那样换算,从00000001到01111111依次表示1到127。那么这些数对应的二进制码就是这些数的原码(和原码一样)。到这里很多人就会想,那负数是不是从10000001到11111111依次表示-1到-127,那你发现没有,如果这样的话那么一共就只有255个数了,因为10000000的情况没有考虑在内。所以-1到-127不能那样表示(和原码的表示方法相同了,当然错了)。实际上,10000000在计算机中表示最小的负整数,即-128(原指-0的)。因为 -128+1=-127,那么把10000000加上1即10000001表示-127就容易计算很多了。这样,从10000001到11111111就刚好依次表示-127到-1。这就是所谓的补码。). 那么补码是怎样直接地转换得来呢?负数的补码就是对反码加一;而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:
(-128~0~127)共256个.
注意:当字长为8位时,(-128)没有相对应的原码和反码, (-128) = (10000000) (为什么?还有为什么8位整数表示的范围是-128~127,而不是-127~128呢?想过没有,为什么二进制10000000在原码和反码中表示0,在补码中它不表示0,保证了0表示的唯一性,但是它为什么表示负数,而不是正数,你也许会说,因为它符号位是1呀,表示负数呀,对,继续,+128我们用补码怎么表示,包括符号位,表示为010000000,超过了2个字节,如果截取低8位,那么是10000000,最高位(符号位)是1,表示的是一个负数了!我们再看看-128的机器码是多少,原码110000000,反码101111111,补码110000000,截取低8位即10000000,表示的是一个负数。)
补码的加减运算如下:
( 1 ) 10- ( 1 ) 10= ( 1 )10 + ( -1 )10 = ( 0 )10
(00000001)补 + (11111111)补 = (00000000)补 = ( 0 ) 正确
( 1 ) 10- ( 2) 10= ( 1 )10 + ( -2 )10 = ( -1 )10
(00000001) 补+ (11111110) 补= (11111111)补 = ( -1 ) 正确
所以补码的设计目的是:
⑴使符号位能与有效值部分一起参加运算,从而简化运算规则.
⑵使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计
所有这些转换都是在计算机的最底层进行的,而在我们使用的汇编、C等其他高级语言中使用的都是原码。看了上面这些大家应该对原码、反码、补码有了新的认识了吧!int 被设计为计算机处理效率最高的整数类型。很显然,溢出只能出现在两个同符号数相加或两个异符号数相减的情况下。