位运算因为是直接二进制位操作,所以运行很快,在一些jdk源码里面看得见,一般开发web用不到,现在我们来讨论下位运算
以下为了方便显示,使用 八位二进制表示
说明一下:
负数在计算机中的存在形式
以补码的形式存在
负数转二进制:
1.写出x的绝对值的二进制值
2.对这个二进制值取反
3.对取反后的数加1
1. ~ 按位取反(单目运算符)
概念:操作一个二进制数,是1就变成0,0就变成1
例:~10 => ~00001010 => 11110101 => -11
二进制表示的最高位表示正负,1是负,0是正,11110101 转十进制就是 -1 然后取反加负号,就是 11110100 取反,就是 -00001011 就是 - 11
2. ^ 按位异或(双目运算符)
概念:操作两个二进制数,相同的位相异就是1,相同就是0
例: 10^5 => 00001010 ^ 00000101 = > 000001111 =>15
3. & 按位与(双目运算符)
概念:操作两个二进制数,相同的位只要有一个是0,那么该位运算后的结果就是0
例:10&5 =>00001010 & 00000101 => 00000000 => 0
4. | 按位或(双目运算符)
概念:操作两个二进制数,相同的位只要有一个是1,那么该位就是1
例:10|5 => 00001010 | 00000101 => 00001111 => 15
eclipse运行控制台截图如下
顺便说一下位运算在进制转换中的应用
例如将八位二进制的(可以理解成byte类型)数转成两位16进制的数
// 首先初始化一个字符数组,用来存放每个16个字符
private static final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f' };
public static void main(String[] args) {
byte b = 123;
// 因为一个 byte 类型的占 8位,一个16进制的占4位,所以8位二进制的可以看作是 两位十六进制的
char [] c = new char[2];
c[0]= hexDigits[b >>> 4 & 0xf]; // 这里使用在数组里面取的原因是int转char有时候会变成ascll里面的值,输出就不准确了
c[1]= hexDigits[b & 0xf];
System.out.println(new String(c));
}
解释一下:因为 b是八位二进制的,比如说 20 ,二进制就是 00010100 转成十六进制,因为一个十六进制的数可以看作是4位二进制的,从左往右的数就是相当于十进制里面的 百位,十位,个位,将二十直接右移四位,就是 只有前面的四位了,其他的补零,就是 00000001 ,然后按位要做的就是计算 00000001的值,其实这里也可以不和 0xf(00001111)按位与,直接输出也就是十进制的值,但是这只是恰巧,最好还是与一下,然后转成十六进制的第一位就是1,然后再直接(20(00010100)不移位)和0xf(00001111)按位与,按位与可以除去前面的1,只要后面的四位,结果就是,00000100 就是4,所以十进制的20转十六进制就是 14.运行如下图所示
再例如,20转八进制
public static void main(String[] args) {
byte b = 20;
// 因为一个 byte 类型的占 8位,一个8进制的占3位,所以8位二进制的可以看作是 三位八进制的(不够的补零)
char [] c = new char[2];
c[0]= hexDigits[b >>> 6 & 7]; // 7的二进制就是 00000111,移位之后与的值就是转成八进制之后的值
c[0]= hexDigits[b >>> 3 & 7];
c[1]= hexDigits[b & 7];
System.out.println(new String(c));
}
运行结果如图: