素数判断:
通常判断一定范围内的素数第一反应是采用暴力穷举来判断,如一下代码
public static void main(String[] args) {
int n = 100;
Main m = new Main();
for(int i=2; i<=n; i++)
{
m.printPrime(i);
}
}
void printPrime(int n){ //判断n是否是质数
boolean isPrime=true; //是否是质数的标志
for(int i=n-1;i>1;i--){ //n除以每个比n小比1大的自然数
if(n%i==0){ //如果有能被整除的,则不是质数
isPrime=false;
}
}
if(isPrime){//如果是质数,则打印出来
System.out.print(n+" ");
}
}
这个方法可以快速的找出质数,但是计算量很大,不是很好!
看书发现了一个有用的类 BitSet , BitSet 实际是由“二进制位”构成的一个Vector。
而且书中给出了查找质数的方法,代码如下
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 100;
long start = System.currentTimeMillis();
BitSet b = new BitSet(n+1);
System.out.println(" o " + b.get(0));
int count = 0 ;
int i;
for(i=2 ; i<n ; i = i+1){
b.set(i);
}
System.out.println(" 3 " + b.get(3));
i=2;
while(i*i <= n){
if(b.get(i)){
System.out.println(" * "+i );
count ++ ;
int k = 2*i;
while(k<=n){
b.clear(k);
k = k + i;
}
}
i++;
}
while(i<=n){
//if(b.get(i)) count++;
i++;
}
long end = System.currentTimeMillis();
System.out.println(count + " primes");
System.out.println((end - start) + " milliseconds");
}
核心的思路就是首先把所有的位都设置开的状态,然后把已知素数的倍数位置都设置为关,经过这个操作保留下来的就是素数。
在这里需要说明的有
1 while 循环开始的时候 i*i < n 是因为,距离质数最小的合数是由2个数字相乘而来的,相乘的数字按照大小排列的话,在i时 ,比i 小的数字都已经循环过了,由此可知 比i 大的数字也判断过了: exp : 2 x 5 =10 , 循环2的倍数时,5 已经被乘过,所以是 i 的平方小于 n.
2 遍历的时候从2开始 所有倍数采用加法的方式 表现在 j=i*2 和 j=j+i;
exp : 传入2 j = 4 –> j=4+2 –>j=6+2, 这样一步一步的把所有的倍数都找出来,并清空bitset的位,
判断2000000以内的素数已经成为了曾是编译程序性能的一种流行的基准。