今天总结一下位运算

 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