二进制与位运算
二进制与位运算
补码
计算机中,为了方便计算,整数一般在计算机中都以补码的形式存储
- 补码的计算公式:
- 正数:原码,反码,补码都相同
- 负数:补码 = 反码 + 1
- 负数在计算补码的过程中,符号位保持不变,其他位取反+1
- 补码与原码的转换
- 正数:补码、反码、原码都相同
- 负数:
- 补码->原码 :取反 +1
- 原码->补码: 取反 + 1
Java中的位运算
位运算概述
&:按位与|:按位或~:按位非^:按位异或>>:右移<<:左移>>>:无符号右移
位运算详解
为了演示方便,以下位运算均以8位的byte进行操作,且计算机中位运算都是以补码的形式参与位运算
按位与
同为1则位1,否则为0
8 & 11:00001000 & 00001011 = 00001000 结果为8
-8 & 11:11111000(补码) & 00001011 = 00001000 结果为8
按位或
全0为0,否则为1
8 | 11:00001000 | 00001011 = 00001011 结果为 11-8 | 11:11111000(补码) | 00001011 = 11111011(补码) 求得原码: 10000101 结果为-5
按位非
直接取反,遇1则0,遇0则1
~8:00001000 按位非-> 11110111(得到补码) 计算原码->10001001 结果为 -9
~-8:11111000 按位非->00000111 ->正数补码就是原码,结果为7
按位异或
相同为0,不同为1
8 ^ 11:00001000 按位异或 00001011 = 00000011 结果为3- 再次与11进行异或: 00000011 ^ 00001011 = 00001000 结果有变回8
- 结论:异或一个相同的数字偶数次,结果仍为这个数字
左移
<< : 左移运算符,将操作书的二进制整体左移,右边补0
- 正数的左移n位,结果为 正数 * 2的(n%数据类型的长度)次方,
右移
>>:将操作书的二进制整体右移指定位数,空出的位以符号位为准填充
- 正数的右移n位,结果为 正数/2的(n%数据类型长度)次方
- 负数右移最终结果为-1,因为'111111111111111111111'就是-1的补码形式
无符号右移
低位舍弃,高位补0
位运算的优先级
- ~
- << >> >>>
- &
- ^
- |
常见的位运算应用
对于任意整数a和b,以下表达式结果均成立
- a | 0 == a
- a & 0 == 0
- a & -1 == a (-1的补码是一串1)
- a^a == 0
- a ^ 0 == a
- a |(a &b) ==a
- a &(a | b) == a
常见应用
- 判断奇偶数
a & 1 == 0:a为偶数
a & 1 == 1:a为奇数
原理:偶数的二进制的最后一位为0,而奇数的最后一位为1,而参与位运算的1除了最后一位为1,其余全为0,结果也是不言而喻,偶数的结果就是0,奇数最后一位1&1,结果就为1 - 交换变量
一个整数异或一个相同的数偶数次,其结果仍为这个数字.
int a = 2;
int b = 3;
a ^= b;
b ^= a;//b = b^a 拆开来就是 b = b ^(a ^b) 此时b就=a了
a ^= b;//a = a^b 拆开来就是 a = (a ^b) ^ b 此时a就=b了
- 变换符号
System.out.println(-2 == (~2 +1));结果为true,~a + 1 等价于 -a - 求绝对值
int i = a>>(a的长度-1);//此处长度指的是基本数据类型short,byte,int,long的长度,如果a是整数则得到的结果为0,负数则为-1
System.out.println( i == 0?a:(~a + 1));
5.取余运算
a%b == a&(b-1) 注意:只有b为2的n次方的时候可以使用此方法

浙公网安备 33010602011771号