`
prowl
  • 浏览: 79391 次
  • 性别: Icon_minigender_1
  • 来自: 艾泽拉斯
社区版块
存档分类
最新评论

最近老是在二进制数制上举棋不定,花了1上午时间翻阅资料,记录下来!!

    博客分类:
  • j2se
阅读更多
先列几个概念:

1、原码:

原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用1表示负号,数值一般用二进制形式表示。数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).这就是机器数的原码了.假设机器能处理的位数为8.即字长为1byte,原码能表示数值的范围为:(-127~-0 +0~127)共256个


例:
     7的原码:0000 0111
   -7的原码:1000 0111

7+(-7): 0000 0111 + 1000 0111 = 1000 1000 = 120(显然不对)

所以引入了 2、反码 :

反码可由原码得到。如果机器数是正数,则该机器数的反码与原码一样;如果机器数是负数,则该机器数的反码是对它的原码(符号位除外)各位取反而得到的。反码的取值空间和原码相同且一一对应。

例:
    5的原码:0000 0101
   -7的反码:1111 1000(原码:1000 0111 除符号位按位取反)

5+(-7): 0000 0101 + 1111 1000 = 1111 1101(反) = 10000010(原) = -2 (正确)

1+(-1):0000 0001 + 111111110 = 1111 1111 = -0 (错误)

问题出现在(+0)和(-0)上,在人们的计算概念中零是没有正负之分的.(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大).

于是就引入了3、补码:

负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:(-128~0~127)共256个。

注意:

1.(-128)没有相对应的原码和反码, (-128) = (10000000)

2.正数的补码、反码都和原码一样



4、关于右移(>>)和无符号右移(>>>)

	byte b = (byte) 0xf1;
	byte c = (byte) (b >> 4);// 有符号右移
	byte d = (byte) (b >>> 4);// 无符号右移(即高位自动填充0)
	byte e = (byte) ((b & 0xff) >> 4);
	System.out.println(b);
	System.out.println(c);
	System.out.println(d);
	System.out.println(e);


结果:
-15
-1
-1
15


为什么c和d的结果是一样的,而e却实现了无符号右移?

首先,在执行b>>4或b>>>4操作时jvm都会先将b转为int型:

1111 1111,1111 1111,1111 1111,1111 0001

>>4 : 1111 1111,1111 1111,1111 1111,1111 1111
>>>4: 0000 1111,1111 1111,1111 1111,1111 1111

转为byte时,截取后8位:1111 1111 其为 -1 的补码。

而先执行了(b & 0xff)操作之后其转为int的二进制:

0000 0000,0000 0000,0000 0000,1111 0001

>>4: 0000 0000,0000 0000,0000 0000,0000 1111

转byte: 0000 1111 故结果为:15

移位操作特别注意:比如int型右移x位, 实际上执行的操作时 x=x%32,所以右移32位实际上是右移了0位!!



分享到:
评论
3 楼 xu_ch 2009-11-27  
补码=反码+1
2 楼 prowl 2009-11-26  
langyu 写道
因为补码的存在问题,我纠结了很长时间

之前一直用却不清楚这些概念,今天花时间好好看看,其实不难~
1 楼 langyu 2009-11-26  
因为补码的存在问题,我纠结了很长时间

相关推荐

Global site tag (gtag.js) - Google Analytics