阅读《Java核心技术》的时候,读到了BitSet这个集合。
有一个例子是Eratosthenes 之筛算法,这个算法的主要做用是查找必定范围以内的全部质数,对此比较感兴趣,因此用Boolean数组和BitSet各作了一遍,又在两台电脑上各实现了两种算法。java
在实现的过程当中,遇到了一些问题,会在最后提出,这里不说废话了,先说正事~算法
因为一个合数老是能够分解成若干个质数的乘积,那么若是把质数(最初只知道2是质数)的倍数都去掉,那么剩下的就是质数了。
例如要查找100之内的质数,首先2是质数,把2的倍数去掉;此时3没有被去掉,可认为是质数,因此把3的倍数去掉;再到5,再到7,7以后呢,由于8,9,10刚才都被去掉了,而100之内的任意合数确定都有一个因子小于10(100的开方),因此,去掉,2,3,5,7的倍数后剩下的都是质数了。数组
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)); } }
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的性能仍是稍微好一些的。测试
可是!可是!可是!spa
我在另一台电脑上用相同的代码跑出来的结果却很不同。命令行
另一台电脑跑出来的结果,利用数组实现(也就是上面的ArrayTest)的速度很是快,常常时间在16-32毫秒之间。而用BitSet实现(也就是上面的BitSetTest)的倒是150-160左右。code
两台机器的配置是同样的,win7,32位,4GB,3.2GHZ。
一开始觉得是编译器的问题,后来发现不用编译器用命令行获得的结果也是有差别的。blog
算法的原理和实现已经懂了一些,可是带出来了这些问题,有木有大神解释一下啊。ip