先讲一下定义
素数,又称质数,是只有两个正因数(1和自己)的自然数
像 2,3,5,7,11,13,17,19,23...都是素数;
比1大但不是素数的数称之为和数;
而1和0既非素数也非合数。
求素数的方法有很多种,这里我主要介绍两种
第一种
所有的自然数都可以用(6N,6N+1,6N+2,6N+4,6N+5)中的一个模型表示出来,
可以知道在N>=1的时候,只有(6N+1,6n+5)才有可能是素数,即为(6N+-1)
private static void getSushu(){ long start = System.currentTimeMillis(); int counts = 2; int number = 3;
System.out.println(2);//2 System.out.println(3);//3 List<Integer> primes = new LinkedList<Integer>();
//因为下面刷选中不包括2.3
primes.add(2);
primes.add(3); for (int i=3;i<= 200000;i+=3) { for(int j=0;j<=1;j++) { //任何数都能用(6N;6N+1;6N+2;6N+3;6N+4;6N+5 表示) //当N>= 1 的时候,只有6N+1,6N+5可能是素数,即6N+-1 //用2*(i+j)-1就表示 6N+_1 ,其中 i是3的倍数,j是0-1的循环
number = 2*(i+j)-1;//刷选出可能成为素数的数
if(number < 200000){//取出 200000以内的素数
if(check(number))//判断是否是素数 { primes.add(number); counts += 1; //System.out.println(number); } } else{ long end = System.currentTimeMillis(); System.out.println("times:" + (end - start)); System.out.println("counts: " + counts); return; } } } }
private static boolean check(int number){ for(int k = 2; k <= Math.sqrt(number); k++) { if(number % k == 0) { return false; } } return true; }
第二种
是以空间换时间的方式求素数
java中的BitSet是由二进制位构成的一个vector
通过标记bitset每一位的开关,判断是否为素数
private static void getSushu(){ long start = System.currentTimeMillis(); int n = 200000;//200000以内的素数 BitSet b = new BitSet(n + 1);//新建一个n+1位的bitset List<Integer> primes = new LinkedList<Integer>();//存放素数 int i = 0; for (i = 2; i <= n; ++i) { b.set(i); // 设置此位置上的位为true,即所有位都为素数 }
//从2开始,排除2的倍数;以此类推,排除3,4,5..sqrt(n)的倍数 i = 2; int k = 0; while (i * i <= n) { if (b.get(i)) { primes.add(i); k = 2 * i; while (k <= n) { b.clear(k); // 清除此位置上的位为false,则该位不为素数 k += i; } } ++i; }
//剩下的判断,如果位true,则为素数 while (i <= n) { if (b.get(i)) { primes.add(i); } ++i; } //System.out.println(primes); System.out.println("counts :" + primes.size()); long end = System.currentTimeMillis(); System.out.println("times:" + (end - start)); }
在我电脑上做得测试
celeron(R) 2.40
内存:1GB
两种方法对比,在算2500万以内素数时,第一种方法需要3分钟左右,第二种方法只要9秒左右