开始之前,想必大家都很熟悉这样一道面试题:
java面试题int a=2*8怎样运算效率最快
用移位运算 int a=2
a就是2乘以8 最后结果是16 这是最省内存 最有效率的方法
解释一下:
2的二进制是10, 在32位存储器里面是0000 0000 0000 0010
左移三位后变成 0000 0000 0001 0000 也就是16
java中的位运算首先要明白一点,这里面所有的操作都是针对存储在计算机中中二进制的操作,那么就要知道,正数在计算机中是用二进制表示的,负数在计算机中使用补码表示的。
左移位:
左移操作时将运算数的二进制码整体左移指定位数,左移之后的空位用0补充
右移位:>>,有符号的移位操作
右移操作是将运算数的二进制码整体右移指定位数,右移之后的空位用符号位补充,如果是正数用0补充,负数用1补充。
扩展:
1.原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
2.反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
3.补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后 1。 (即在反码的基础上 1)
4.原码和反码的相互转换:符号位不变,数值位按位取反
5.原码和补码的相互转换:符号位不变,数值位按位取反,末位再加1
6.已知补码,求原码的负数的补码:符号位和数值位都取反,末位再加1
例子:
public static void main(String[] args){System.out.println(32);//6右移2位System.out.println(-6>>2);//-6右移2位}输出结果12-121-2下面解释一下:
00000000 00000000 00000000 00000011 3在32位计算机中表示
00000000 00000000 00000000 0000001100 左移2位,补0,结果为12
----------------------------------------------------------------------------------------------
00000000 00000000 00000000 00000011 3在在32位计算机中表示
11111111 11111111 11111111 11111100 取反码
11111111 11111111 11111111 11111101 -3在计算机中表示(反码 1)
11111111 11111111 11111111 1111110100 左移2位,补0,结果为负数,就是补码了,
10000000 00000000 00000000 00001011 求原码
10000000 00000000 00000000 00001100 结果-12
----------------------------------------------------------------------------------------------
00000000 00000000 00000000 00000110 6在计算机中表示方法
0000000000 00000000 00000000 000001 右移两位,正数补0,结果为1
----------------------------------------------------------------------------------------------
00000000 00000000 00000000 00000110 6在32位计算机中表示方法
11111111 11111111 11111111 11111001
11111111 11111111 11111111 11111010 -6在在32位计算机中的表示
1111111111 11111111 11111111 111110 右移两位,结果为负数
1000000000 00000000 00000000 000001
1000000000 00000000 00000000 000010 结果为-2
这个地方很容易弄混,多想几次就会慢慢理解了。
上面解释了带符号的移位操作,下面解释一下不带符号的移位操作
无符号的移位只有右移,没有左移,使用“>>>”进行移位,都补充0
例如:
public static void main(String[] args){System.out.println(6>>>2);System.out.println(-6>>>2);}结果:11073741822分析:
00000000 00000000 00000000 00000110 6在计算机中表示方法
0000000000 00000000 00000000 00000110 右移两位,正数补0,结果为1
-----------------------------------------------------------------------------------------------
00000000 00000000 00000000 00000110 6在计算机中表示方法
11111111 11111111 11111111 11111001
11111111 11111111 11111111 11111010 -6在计算机中的表示
0011111111 11111111 11111111 11111010 右移两位,补充0,结果为1073741822
补充移位操作要注意的问题是高(低)位是补0还是补1和对char, byte, short型的操作:
(1)
(2)>> : (signed right-shift), 右移过程使用符号位扩展(sign extension),即如果符号为1则高位补1, 是0则补0,也就是逻辑右移
(3)>>> : (unsigned right-shit),右移过程使用零扩展(zero extension),即最高位一律补0,也就是算术右移
(4)移位操作的数据类型可以是byte, char, short, int, long型,但是对byte, char, short进行操作时会先把它们变成一个int型,最后得到一个int型的结果,对long型操作时得到一个long型结果,不可以对boolean型进行操作。
(5)移位操作符可以和=合并起来,即 <>= 和 >>>=。例如 a >>= 2; 表示将a右移两位后的值重新赋给a。当时在使用这三个操作符对 byte, char, short型数据进行操作时要注意,例如有一下代码片段:
public class ShiftTest{public static void main(String [] args){byte a;byte b;byte c;a = 127;b = 127;c = 127;a 这说明了在操作a 总结移位操作的简单计算方法
>>右移操作
x>>y
就是x除以2的y此方,取最小整数
X
就是x乘以2的y次方
求java大神告诉我 java中无符号左移或右移 是怎么回事呢? 特别是负数是怎么回事?谢谢了
有符号就带符号、没符号就补0。转成2进制,或者自己用筷子摆几下,就清楚了。
借个别人写好的了
右移
System.out.println(-3>>1);结果是-2,为什么会是-2呢?下面我们来看一下.System.out.println(Integer.toHexString(-3));得到-3的16进制为fffffffd(此为-3的补码,计算机中负数用补码表示).转换成2进制为
1111 1111 1111 1111 1111 1111 1111 1101
右移一位为
1111 1111 1111 1111 1111 1111 1111 1110
,显而易见此为-2补码.
左移
System.out.println(-3<<1);左移相对来说比较简单.1111 1111 1111 1111 1111 1111 1111 1101左移一位为1111 1111 1111 1111 1111 1111 1111 1010,其为-6的补码.
无符号右移System.out.println(-3>>>1);1111 1111 1111 1111 1111 1111 1111 1101无符号右移,高位补0,01111 1111 1111 1111 1111 1111 1111 1110,其为2147483646的原码.