位图技术

本文详细介绍了位运算的基本概念,包括与、或、非、异或及移位运算符,并通过具体示例展示了它们的工作原理。此外,还提供了一个位图向量的实现示例,展示了如何利用位运算来高效管理大量位的状态。

一、基本概念

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 class ShiftTest
{
    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 }

 


       

 

转载于:https://www.cnblogs.com/Dream-Weaver/archive/2013/05/05/3059853.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值