定点数据再计算机中的表示方法
例如一个整数类型(int)的数据在内存中占用了32位。通俗的讲就是在内存中挖了32个坑,每一个坑里可以放一个0或者1.
00000000 11111111 00000000 11111111
32个坑,每一个坑有两种可能,那么总共就是2^32种可能。
整数既有正整数,又有负整数,还有一个零,那么分2^32分一半的可能(2^31)给负整数,分一种可能给0,还剩下2^31-1种可能给整整数。
这就是为啥整数类型(int)只能表示-2^31~2^31-1数值范围的整数了。
我们知道整数类型(int)中,正整数就可以标示成:
00000000 00000000 00000000 00000000 =>表示整数0;
00000000 00000000 00000000 00000001 =>表示整数1;
00000000 00000000 00000000 00000010 =>表示整数2;
....
00000000 00000000 11111111 11111111 =>表示整数2^31-1
那么负整数就可以标示成:
11111111 11111111 11111111 11111111 =>标示整数-1;
11111111 11111111 11111111 11111110 =>表示整数-2;
11111111 11111111 11111111 11111101 =>表示整数-3;
...
11111111 11111111 00000000 00000001 =>表示整数-2^31-1
11111111 11111111 00000000 00000000 =>表示整数-2^31
看到这里,像我一样聪明的小伙伴肯定可以看出正整数和其对应的负整数之间的关系:妈蛋,它们就是把正整数所有的0变成1,把1变成0,然后在加上1.
把正整数所有的0变成1,把1变成0,然后在加上1这是通俗的叫法,其实术语叫按位取反。
位运算符&, |, ~, ^
位运算符与逻辑运算符类似,但是位运算符是对每一位进行计算。
op1[i] | op2[i] | op1[i]&op2[i] | op1[i] | op2[i] | op1[i]^op2[i] | ~op1[i] |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 1 |
0 | 1 | 0 | 1 | 1 | 1 |
1 | 0 | 0 | 1 | 1 | 0 |
1 | 1 | 1 | 1 | 1 | 0 |
上面说到的按位取反加1,就可以写成:
System.out.print(~10+1); //-10
移位运算符 >>, >>>, <<
右移>>与无符号右移>>>相似,
op1>>op2 是将整数op1所有的位向右移动op2位,抛弃op2个低位。空出来的高位用op1的最高位值补全。
op1>>>op2 是将整数op1所有的位向右移动op2位,抛弃op2个低位。空出来的高位用0的最高位值补全。
op1<<op2 是将整数op1所有的位向左移动op2位,抛弃op2个高位。空出来的低位用0的最高位值补全。
没有<<<哦,亲~~~
按位异或运算的性质
(a^b)^a = b
我们来取a和b的第i位剖析一下,a,b 总共四种可能:
a[i] | b[i] | a^b[i] | a^b[i] |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
可以发现(a^b)^a与a的值是一样的。
所以如果我们这么写的话:
a = a^b;
b = a^b; //b = (a^b)^b = a
a = a^b; // a = (a^b)^a = b
就能实现a、b交换数值。