首先谈之前需要明白一下几点:
1 对于数字 在计算机中存贮和计算都是以补码的形式 正数的补码和反码就是它本身 负数的补码是反码+1 注意对于有符号的数字 最高位表示符号位 0表示正 1表示负
2 之所以用补码进行计算和存储的原因:
1)使符号位能与有效值部分一起参加运算,从而简化运算规则。从而可以简化运算器的结构,提高运算速度;(减法运算可以用加法运算表示出来。)
2)加法运算比减法运算更易于实现。使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。【从补码运算的特征理解!】
3)为了防止0的机器数有两个编码。
注意:
http://www.360doc.com/content/12/1009/21/10086564_240513741.shtml
3因此 << >> >>>都是对补码进行操作 此点重要 byte 和 char在进行移位操作时候 都是转换为int进行操作
一:<<表示左移运算
左移的规则只记住一点:丢弃最高位,0补最低位
如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模。如对int型移动33位,实际上只移动了1位
举例正数:4
补码:0000 0000 0000 0000 0000 0000 0000 0100(正数补码=原码)
4<<1
=8 0000 0000 0000 0000 0000 0000 0000 1000 此时虽然丢弃了最高位 但是左移后符号并没有改变 仍然为正
---------------------------------------------------------------------
举例负数:-4
补码:11111111111111111111111111111100
-4<<1
= -8 11111111111111111111111111111000 (再取反+1就还原为原码) 此时虽然丢弃了最高位1 但是左移后符号并没有改变 仍然为负
二 >>有符号右移
右移的规则只记住一点:符号位(正负)不变,左边补上符号位(正数左边补0 负数左边补1 有差别 因此叫做有符号右移)
举例正数:4
补码:0000 0000 0000 0000 0000 0000 0000 0100(正数补码=原码)
4>>1
=2 0|000 0000 0000 0000 0000 0000 0000 0010 符号位置正负不变 |左边补0
---------------------------------------------------------------------
举例负数:-4
补码:11111111111111111111111111111100
-4>>1
= -2 1|1111111111111111111111111111000 (再取反+1就还原为原码) 符号位置不变 |左边补上1
三 >>>无符号右移
无符号右移的规则只记住一点:忽略了符号位扩展,0补最高位 (那么此时负数的话会带来正负号变化的问题)
举例正数:4
补码:0000 0000 0000 0000 0000 0000 0000 0100(正数补码=原码)
4>>>1
=2 0000 0000 0000 0000 0000 0000 0000 0010 忽略符号位 直接在符号位左边补0
---------------------------------------------------------------------
举例负数:-4
补码:11111111111111111111111111111100
-4>>>1
= 2147483646 (由负变正 此时为正数 补码以0开头 正数的原码 补码相等 此时补码就是原码)
01111111111111111111111111111110 忽略符号位 直接在符号位左边补0
无符号右移在数据变换时非常重要。
比如对byte b;做无符号右移,在众多散列、加密、压缩、影音媒体编码、序列化格式都会用到。如果没有这个无符号右移,就需要用更大的空间去做有符号右移。
比如byte就需哟short,short就需要int去做,浪费空间和时间。总之,无符号右移的应用场合大大多于有符号右移。(欢迎补充指正)
此处参考:http://www.zybang.com/question/3666fc8d9c9903e808803ca8781670a2.html
四:为什么没有<<<
从上面可以看出,左移是在右边补0 不管正数负数 右边补0 都对符号位不产生影响 不产生符号问题
右移是在左边补,正数补0 负数补1(都是对补码而言)
因此没必要无符号左移 <<<和<<是一样的概念