Eratosthenes 之篩算法(尋找質數)

閱讀《Java核心技術》的時候,讀到了BitSet這個集合。
有一個例子是Eratosthenes 之篩算法,這個算法的主要做用是查找必定範圍以內的全部質數,對此比較感興趣,因此用Boolean數組和BitSet各作了一遍,又在兩臺電腦上各實現了兩種算法。java

在實現的過程當中,遇到了一些問題,會在最後提出,這裏不說廢話了,先說正事~算法

Eratosthenes 之篩算法思路

因爲一個合數老是能夠分解成若干個質數的乘積,那麼若是把質數(最初只知道2是質數)的倍數都去掉,那麼剩下的就是質數了。
例如要查找100之內的質數,首先2是質數,把2的倍數去掉;此時3沒有被去掉,可認爲是質數,因此把3的倍數去掉;再到5,再到7,7以後呢,由於8,9,10剛纔都被去掉了,而100之內的任意合數確定都有一個因子小於10(100的開方),因此,去掉,2,3,5,7的倍數後剩下的都是質數了。數組

Boolean數組實現

public class ArrayTest
{
    public static void main(String[] args) 
    {

        int sum = 0;
        final int TOTAL = 2_000_001;

        Boolean[] array = new Boolean[TOTAL];

        long startTime = System.currentTimeMillis();

        for(int i = 2;i<TOTAL;i++)
        {
            array[i] = true;
        }

        for(int i = 2;i<Math.sqrt(TOTAL);i++)
        {
            for(int j = i;i*j<TOTAL;j++)
            {
                array[i*j] = false;
            }
        }
long endTime = System.currentTimeMillis();
        for(int i = 2;i<TOTAL;i++)
        {
            if(true==array[i])
            {
                sum ++;
            }
        }
        

        System.out.println("There is "+ sum + " prime number");
        System.out.println("Total time is "+ (endTime - startTime));
    }
}

BitSet實現

import java.util.BitSet;

public class BitSetTest
{
    public static void main(String[] args) 
    {

        int sum = 0;
        final int TOTAL = 2_000_001;

        BitSet aBitSet = new BitSet(TOTAL);

        long startTime = System.currentTimeMillis();

        for(int i = 2;i<TOTAL;i++)
        {
            aBitSet.set(i);
        }

        for(int i = 2;i<Math.sqrt(TOTAL);i++)
        {
            for(int j = i;i*j<TOTAL;j++)
            {
                aBitSet.clear(i*j);
            }
        }
long endTime = System.currentTimeMillis();
        for(int i = 2;i<TOTAL;i++)
        {
            if(true==aBitSet.get(i))
            {
                sum ++;
            }
        }
        

        System.out.println("There is "+ sum + " prime number");
        System.out.println("Total time is "+ (endTime - startTime));
    }
}

BitSet和數組的對比結果

而後各測試了三次,測試的結果是這樣子的:性能

clipboard.png

能夠看到三次平均下來,BitSet的性能仍是稍微好一些的。測試

引起思考的問題

可是!可是!可是!spa

我在另一臺電腦上用相同的代碼跑出來的結果卻很不同。命令行

另一臺電腦跑出來的結果,利用數組實現(也就是上面的ArrayTest)的速度很是快,常常時間在16-32毫秒之間。而用BitSet實現(也就是上面的BitSetTest)的倒是150-160左右。code

兩臺機器的配置是同樣的,win7,32位,4GB,3.2GHZ。
一開始覺得是編譯器的問題,後來發現不用編譯器用命令行獲得的結果也是有差別的。blog

算法的原理和實現已經懂了一些,可是帶出來了這些問題,有木有大神解釋一下啊。ip

相關文章
相關標籤/搜索