一、基本概念
1.与运算符
与运算符用符号“&”表示,其使用规律如下:
两个操作数中位都为1,结果才为1,否则结果为0,例如下面的程序段。
public class data13
{
public static void main(String[] args)
{
int a=129;
int b=128;
System.out.println("a 和b 与的结果是:"+(a&b));
}
}
运行结果
a 和b 与的结果是:128
下面分析这个程序:
“a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。
2.或运算符
或运算符用符号“|”表示,其运算规律如下:
两个位只要有一个为1,那么结果就是1,否则就为0,下面看一个简单的例子。
public class data14
{
public static void main(String[] args)
{
int a=129;
int b=128;
System.out.println("a 和b 或的结果是:"+(a|b));
}
}
运行结果
a 和b 或的结果是:129
下面分析这个程序段:
a 的值是129,转换成二进制就是10000001,而b 的值是128,转换成二进制就是10000000,根据或运算符的运算规律,只有两个位有一个是1,结果才是1,可以知道结果就是10000001,即129。
3.非运算符
非运算符用符号“~”表示,其运算规律如下:
如果位为0,结果是1,如果位为1,结果是0,下面看一个简单例子。
public class data15
{
public static void main(String[] args)
{
int a=2;
System.out.println("a 非的结果是:"+(~a));
}
}
4.异或运算符
异或运算符是用符号“^”表示的,其运算规律是:
两个操作数的位中,相同则结果为0,不同则结果为1。下面看一个简单的例子。
public class data16
{
public static void main(String[] args)
{
int a=15;
int b=2;
System.out.println("a 与 b 异或的结果是:"+(a^b));
}
}
运行结果
a 与 b 异或的结果是:13
分析上面的程序段:a 的值是15,转换成二进制为1111,而b 的值是2,转换成二进制为0010,根据异或的运算规律,可以得出其结果为1101 即13。
5、移位运算符
移位操作要注意的问题是高(低)位是补0还是补1和对char, byte, short型的操作:
(1)<< : (left-shift), 最低位补0(左移可以看成是乘以一个数)
(2)>> : (signed right-shift), 右移过程使用符号位扩展(sign extension),即如果符号为为1则高位补1, 是0则补0,也就是逻辑右移(右移可以看成除以一个数)
(3)>>> : (unsigned right-shit),右移过程使用零扩展(zero extension),即最高位一律补0,也就是算术右移
(4) 移位操作的数据类型可以是byte, char, short, int, long型,但是对byte, char, short进行操作时会先把它们变成一个int型,最后得到一个int型的结果,对long型操作时得到一个long型结果,不可以对boolean型进 行操作。
(5)移位操作符可以和=合并起来,即 <<= 、 >>= 和 >>>=。例如 a >>= 2; 表示将a右移两位后的值重新赋给a。当时在使用这三个操作符对 byte, char, short型数据进行操作时要注意,例如有一下代码片段:
{
public static void main(String [] args)
{
byte a;
byte b;
byte c;
a = 127;
b = 127;
c = 127;
a <<= 2;
System.out.println(a);
System.out.println(b <<= 2);
System.out.println(c << 2);
}
}
运行结果是:
-4
-4
508
这 说明了在操作a <<= 2 执行过程是这样的:先将 byte型的数 127变成int型,左移2位得到 508,然后把508赋给byte型变量a时只是简单地"折断"(truncate)得到数-4。编译时编译器不会提示你可能损失精度(实际上在本例中确 实是损失精度了),但是如果你把a <<= 2改成 a = a << 2;编译器就会提示可能损失精度了。
二、构建位图向量
1 public class NBitsVector { 2 private static final int BITS_IN_INT = 32; 3 private static final int SHIFT = 5; 4 private static final int MASK = 0x1f; 5 // 将一个整型数组中的所有整数的位串联成一个位向量 6 private int[] bitsVector; 7 // 位向量的总位数 8 private int bitsLength; 9 public NBitsVector(int n){ 10 int i=1; 11 while(i*BITS_IN_INT<n){ 12 i++; 13 } 14 this.bitsLength=i*BITS_IN_INT; 15 if(bitsVector==null){ 16 bitsVector=new int[i]; 17 } 18 19 } 20 // bitsVector[i>>SHIFT]是第i位应该在第几个int上 21 // (1<<(i & MASK))是第i位在该int上的第几个bit 22 // i&0x1F是i/32的余数 23 /** 24 * setBit: 将位向量的第 i 位置一 25 * @param i 要置位的位置 26 */ 27 public void setBit(int i) { 28 bitsVector[i>>SHIFT]|=1<<(i&MASK); 29 } 30 /** 31 * setBit: 将位向量的第 i位置0 32 * @param i 要置位的位置 33 */ 34 public void clrBit(int i) { 35 bitsVector[i>>SHIFT]&=~(1<<(i&MASK)); 36 } 37 /** 38 * setBit: 判断位向量的第 i位置是否为1 39 * @param i 需要判断的位置的位置 40 */ 41 public boolean testBit(int i) { 42 return (bitsVector[i>>SHIFT]&(1<<(i&MASK)))!=0; 43 } 44 /** 45 * clr: 位向量全部清零 46 */ 47 public void clr(){ 48 for(int i=0;i<bitsVector.length;i++){ 49 bitsVector[i]=0; 50 } 51 52 } 53 /** 54 * getBitsLength: 获取位向量的总位数 55 */ 56 public int getBitsLength(){ 57 return this.bitsLength; 58 } 59 /** 60 * 获取给定整数 i 的二进制表示, 若高位若不为 1 则补零。 61 * @param i 给定整数 i 62 */ 63 public String intToBinaryStringWithHighZero(int i){ 64 String basicResult = Integer.toBinaryString(i); 65 int bitsForZero = BITS_IN_INT - basicResult.length(); 66 StringBuilder sb = new StringBuilder(""); 67 while (bitsForZero-- > 0) { 68 sb.append('0'); 69 } 70 sb.append(basicResult); 71 return sb.toString(); 72 } 73 public String toString() { 74 StringBuilder sb = new StringBuilder("Bits Vector: "); 75 for (int i = bitsVector.length-1; i >=0 ; i--) { 76 sb.append(intToBinaryStringWithHighZero(bitsVector[i])); 77 sb.append(" "); 78 } 79 return sb.toString(); 80 } 81 public static void main(String args[]){ 82 NBitsVector nbv = new NBitsVector(64); 83 nbv.setBit(2); 84 System.out.println(nbv); 85 nbv.setBit(7); 86 nbv.setBit(18); 87 nbv.setBit(25); 88 nbv.setBit(36); 89 nbv.setBit(49); 90 nbv.setBit(52); 91 nbv.setBit(63); 92 System.out.println(nbv); 93 nbv.clrBit(36); 94 nbv.clrBit(35); 95 System.out.println(nbv); 96 System.out.println("52: " + nbv.testBit(52)); 97 System.out.println("42: " + nbv.testBit(42)); 98 nbv.clr(); 99 System.out.println(nbv); 100 } 101 102 }