寻找下一个质数
Martyr2项目实现——Number部分的问题求解(4)Next Prime Number
问题描述:
Have the program find prime numbers until the user chooses to stop asking for the next one
翻译:
给定一个程序,在用户中断程序之前尽可能的寻找素数(可以转化为寻找前N个 素数)
原理:
常用的寻找素数的方法有两种,试除法和筛法
试除法:
判断一个数是否为素数的基本方法就是试除法。
将一个整数n除以每个大于2且小于等于\(\sqrt{n}\)的整数m(可以只使用素数m来检查). 如果 出现可以整除的整数,就说明整数n不是素数;否则所有的整数m都无法被n整除,说明整数 n为素数。
试除法的一个问题是当测试的数目很大时,判断速度会很慢。
素数筛法:
常用的素数筛法是埃拉托斯特尼筛法,可以用于找出一定范围内所有的素数。
算法原理:
从最小的素数2开始,将每个素数的倍数(这些数构成公差为该素数本身的等差数列)都标记为 合数。
对于给定的整数范围n,找出\(\sqrt{n}\)以内的所有素数,并且用这些素数筛除对应的合数
假定\(\sqrt{n}\)以内的素数为\(p_1,p_2,p_3,...p_k,\)对于素数\(p_i\),将它的倍数\(2p_i,3p_i,4p_i,...\)(<=N)都标记为合数,
该筛法的时间复杂度为\(O(n\ln\ln{n})\)
参考文献:埃拉托斯特尼筛法
程序实现:
-
试除法:
public static ArrayList<Integer> MakePrime(int N){ int sqrt_i; ArrayList<Integer> prime_list = new ArrayList<>(); for(int i=2;i<=N;i++){ sqrt_i = (int)Math.sqrt(i); //首先使用已生成的素数表进行试除 if(!prime_list.isEmpty()) { int prime_num = prime_list.size(); for (int j=0;j<prime_num;j++) { int prime = prime_list.get(j); if (prime <= sqrt_i) { if (i % prime == 0)//如果i能被整除,就不是素数,直接跳出当前循环 break; }else{ prime_list.add(i); break; } } int last_prime = prime_list.get(prime_list.size()-1); //如果当前生成的最大素数小于sqrt(i),检查完当前素数表,需要继续试除后续整数 if(i%last_prime!=0&&last_prime<sqrt_i) { int j = last_prime + 1; while (j <= sqrt_i && i % j != 0) j++; if (j > sqrt_i) prime_list.add(i); } }else{ prime_list.add(i); //素数表为空,直接将素数2加入 } } return prime_list; } -
筛法:
public static ArrayList<Integer> MakePrime2(int N){ boolean[] isPrimes = new boolean[N+1]; int sqrt_N = (int)Math.sqrt(N); for(int i=0;i<isPrimes.length;i++){ isPrimes[i] = true; } for(int i=2;i<=sqrt_N;i++){ if(isPrimes[i]) {//如果i是一个素数,就将i的倍数置为False(合数) //将素数对应的倍数置为false for (int j = i * 2; j <= N; j += i) { isPrimes[j] = false; } } } ArrayList<Integer> prime_list = new ArrayList<>(); for(int i=2;i<=N;i++) if(isPrimes[i]) prime_list.add(i); return prime_list; }
运行时间
我们通过计算1亿以内的全部素数,来比较试除法和筛法的运行时间,明显筛法速度快于试除法,但是筛法需要的空间要大于试除法,筛法需要用一个容纳整个搜索范围的数组空间,而试除法只需要一个保存全部素数的数组空间
前100000000个整数中素数的个数:5761455
使用试除法求取素数表的程序运行时间:23933ms
前100000000个整数中素数的个数:5761455
使用筛法求取素数表的程序运行时间:1748ms

浙公网安备 33010602011771号