了解BitSet类并实现素数筛选--Eratosthenes筛选法

今天看到了java集合当中的一个位集BitSet,先说一下BitSet,BitSet类用于存放一个位序列,如果需要高效的存储位序列可以使用位集,因为位集将位包装在了字节里面,所以使用位集要比使用Boolean对象的ArrayList更为高效
BitSet取值为true和false,在API里面有以下几个方法:

BitSet(int initialCapacity)     创建一个位集
int length( )                   返回位集的“逻辑长度”,即1加上位集的最高设置位置的索引值
boolean get(int bit)            获得一个位
void set(int bit)               设置一个位
void clear(int bit)             清除一个位
void and(BitSet set)            这个位集和另一个位集进行逻辑“AND”
void or(BitSet set)             这个位集和另一个位集进行逻辑“OR”
void xor(BitSet set)            这个位集和另一个位集进行逻辑“XOR”(异或运算)
void andNot(BitSet set)         清除这个位集中对应另一个位集中设置的所有位

好的,接下来介绍一下Eratosthenes筛选法(埃拉托斯特尼筛选法),这个算法并不是一种查找素数的最好方法,但是由于某些原因,它已经成为了测试编译程序性能的一种流行的基准(这也不是一种最好的基准测试方法,它主要用于位操作)
Eratosthenes筛选法的主要逻辑就是不必运用除法而找到2~N之间的素数,比如开始是i,想办法把i的倍数都筛选出去,然后剩下的数就是质数

例子是求2~2000000之间的所有素数
代码:

import java.util.BitSet;

public class Eratosthenes {
    public static void main(String[] args) {
        int n = 2000000;    //判断2000000以内的素数
        BitSet b = new BitSet(n+1); 
        int count = 0;
        int i;
        for(i = 2; i <= n; i++) //把各个位都置为true
            b.set(i);
        i = 2;
        while(i * i <= n){  
            if(b.get(i)){   
                System.out.println(i);
                count++;
                int k = 2 * i;  
                while(k <= n){  //筛选掉i的倍数的数,i的倍数一定能被i整除,i的倍数一定不是素数
                    b.clear(k); //将i的倍数位置为false
                    k += i;
                }
            }
            i++;
        }
        while(i <= n){  //判断i以后的数的位是否为true
            if(b.get(i))
                count++;
            i++;
        }
        System.out.println("一共有"+count+"个素数");
    }
}

其实这个算法有很多可以优化的地方,比如除了2以外的偶数一定不是素数,所以可以只考虑奇数,写这篇文章的主要目的就是记录一下BitSet这个类的用法
BitSet是可以按位存储的,我们知道,在计算机中一个字节(byte)占8位(bit),而且在java里面数据至少得是按字节存储的,如果遇到大的数据量的话,就相当的占用内存了
比如说一个int占4个字节,就是4*8=32位(bit)
当我们存储一个整型2的话,用BitSet的话就可以用到一个位,因为BitSet是这样进行的,先声明一个BitSet,大小为2+1,然后将第2位设置为true,最后的结果是[false,false,true],所以它存的是整数2,只用了一个位就搞定了,占用的内存比例可是32:1,极大地节省了存储空间。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章