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

相关文章
相关标签/搜索