瞭解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,極大地節省了存儲空間。

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