先列几个概念:
[b]1、原码:[/b]
[b][color=red]原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用1表示负号,数值一般用二进制形式表示。[/color][/b]数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).这就是机器数的原码了.假设机器能处理的位数为8.即字长为1byte,原码能表示数值的范围为:(-127~-0 +0~127)共256个
例:
7的原码:0000 0111
-7的原码:1000 0111
7+(-7): 0000 0111 + 1000 0111 = 1000 1000 = 120(显然不对)
所以引入了 [b]2、反码 :[/b]
[color=red][b]反码可由原码得到。如果机器数是正数,则该机器数的反码与原码一样;如果机器数是负数,则该机器数的反码是对它的原码(符号位除外)各位取反而得到的。反码的取值空间和原码相同且一一对应。[/b][/color]
例:
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)上,在人们的计算概念中零是没有正负之分的.(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大).
于是就引入了[b]3、补码: [/b]
[b][color=red]负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:(-128~0~127)共256个。[/color]
[color=blue]注意:
1.(-128)没有相对应的原码和反码, (-128) = (10000000)
2.正数的补码、反码都和原码一样
[/color][/b]
4、关于右移(>>)和无符号右移(>>>)
结果:
为什么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
[color=red][b]移位操作特别注意:比如int型右移x位, 实际上执行的操作时 x=x%32,所以右移32位实际上是右移了0位!![/b][/color]
[b]1、原码:[/b]
[b][color=red]原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用1表示负号,数值一般用二进制形式表示。[/color][/b]数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).这就是机器数的原码了.假设机器能处理的位数为8.即字长为1byte,原码能表示数值的范围为:(-127~-0 +0~127)共256个
例:
7的原码:0000 0111
-7的原码:1000 0111
7+(-7): 0000 0111 + 1000 0111 = 1000 1000 = 120(显然不对)
所以引入了 [b]2、反码 :[/b]
[color=red][b]反码可由原码得到。如果机器数是正数,则该机器数的反码与原码一样;如果机器数是负数,则该机器数的反码是对它的原码(符号位除外)各位取反而得到的。反码的取值空间和原码相同且一一对应。[/b][/color]
例:
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)上,在人们的计算概念中零是没有正负之分的.(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大).
于是就引入了[b]3、补码: [/b]
[b][color=red]负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:(-128~0~127)共256个。[/color]
[color=blue]注意:
1.(-128)没有相对应的原码和反码, (-128) = (10000000)
2.正数的补码、反码都和原码一样
[/color][/b]
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
[color=red][b]移位操作特别注意:比如int型右移x位, 实际上执行的操作时 x=x%32,所以右移32位实际上是右移了0位!![/b][/color]