今天总结一下位运算
1 package 位操作; 2 3 public class SimpleDemo01 { 4 5 /** 6 * @param args 7 */ 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 int x=3; 11 //00000000 00000000 00000000 00000011 12 int y=6; 13 //00000000 00000000 00000000 00000110 14 //0是false,非0是true 15 System.out.println(x+"&"+y+"="+(x&y)); 16 //00000000 00000000 00000000 00000011 17 //00000000 00000000 00000000 00000110 18 //将上面的每一位进行&操作(即都是真才为真) 19 //00000000 00000000 00000000 00000010 就是2 20 System.out.println(x+"|"+y+"="+(x|y)); 21 //00000000 00000000 00000000 00000011 22 //00000000 00000000 00000000 00000110 23 //将上面的每一位进行|操作(即有一个真就是真) 24 //00000000 00000000 00000000 00000111 就是7 25 26 System.out.println(x+"^"+y+"="+(x^y)); 27 //00000000 00000000 00000000 00000011 28 //00000000 00000000 00000000 00000110 29 //将上面的每一位进行^操作(真假不同才是真) 30 //00000000 00000000 00000000 00000101 就是5 31 32 System.out.println(x+"取反"+~x); 33 //00000000 00000000 00000000 00000011 这即是正数的原码,反码和补码。(正数的反码和补码就是它本身),在取反的时候是将所有位数取反 34 //11111111 11111111 11111111 11111100 这是某个负数的补码,下面将它还原为原码 35 //11111111 11111111 11111111 11111011 补码减1是反码,在由原码变为反码时,第一位符号位不变 36 //10000000 00000000 00000000 00000100 取反得到-4 37 int z=-3; 38 System.out.println(z+"取反"+~z); 39 //10000000 00000000 00000000 00000011 40 //11111111 11111111 11111111 11111100 -3的反码 41 //11111111 11111111 11111111 11111101 -3的补码,这才是计算机中真正的数据 42 //00000000 00000000 00000000 00000010 就是2 43 44 //左移(<<)和右移(>>) 45 //左移是将二进制码整体向左移,左移之后的空位用0填充 46 //右移是将二进制码整体向右移,右移之后的空位用符号位填充。正数用0,负数用1 47 System.out.println("3左移两位"+(x<<2));//x<<n就相当于x乘以2的n次方 48 //00000000 00000000 00000000 00000011 49 //00 00000000 00000000 00000000 00001100 就是12 50 System.out.println("3右移两位"+(x>>2));//x>>n就相当于x整除2的n次方 51 //00000000 00000000 00000000 00000011 3的补码 52 //00000000 00000000 00000000 00000000 11 就是0 53 System.out.println("3无符号右移"+(3>>>2));//无符号右移空位都用0填充 54 //00000000 00000000 00000000 00000011 3的补码 55 //00000000 00000000 00000000 00000000 11 就是0 56 57 58 System.out.println("-3左移两位"+(z<<2)); 59 //10000000 00000000 00000000 00000011 -3的原码 60 //11111111 11111111 11111111 11111101 -3的补码 61 //11 11111111 11111111 11111111 11110100 -12的补码 (左移都补0) 62 System.out.println("-3右移两位"+(z>>2)); 63 //10000000 00000000 00000000 00000011 -3的原码 64 //11111111 11111111 11111111 11111101 -3的补码 65 //11111111 11111111 11111111 11111111 -1的补码 66 System.out.println("-3无符号右移两位"+(z>>>2)); 67 //10000000 00000000 00000000 00000011 -3的原码 68 //11111111 11111111 11111111 11111101 -3的补码 69 //00111111 11111111 11111111 11111111 -1的补码//无符号右移空位都用0填充 70 //没有无符号左移 71 } 72 73 /* 74 * 1、10001的补码是取反后在再加1,也就是11110+1=11111; 75 2、如果是11111变回原码呢?我们可以采取逆过程先减1,11111-1=11110,再取反变为10001; 76 3、如果要是在补码变原码时先去反再加一呢?(就是问题中的说法)结果为11111先取反为10000,再加1,10000+1=10001。这个结果与2是一样的,并且也是和1中的原码相吻合。 77 通过上述例子可以看出,无论是原码变补码还是补码变原码,都可以采取先取反再加1的方法。至于原因是很容易想通的。 78 按照正常思维来想的话,补码变成原码应该是原码变补码的逆过程,也就是2步中的方法。但是我们可以思考一下,如果我们没有按照2步中的方法而是先去取反了呢? 79 先取反得到的结果和2步的结果有什么差异呢?答案是差了1,2步中是先减1才取的反,而直接取反的话,就没有减1。 80 接着请注意,在取反前减1和在取反后加1的效果是一样的。这就和-3-1=-(3+1)是一个道理。 81 所以问题中的说法没有错误。 82 83 所以无论是原码变补码还是补码变原码,都可以采取先取反再加1的方法。 84 */ 85 }
上述代码运行结果:
3&6=2
3|6=7
3^6=5
3取反-4
-3取反2
3左移两位12
3右移两位0
3无符号右移0
-3左移两位-12
-3右移两位-1
-3无符号右移两位1073741823