这些求质数的算法,都是小编一点一点看的大佬们的方法,自己积累的,如果有什么描述的不对的地方还望大佬赐教,多交流才能进步,加油,冲冲冲!!! Bitmap对筛法的空间优化(主要是空间优化,当然也有效率优化)
最基础的暴力求质数
//最基础的暴力求质数(我觉得这个的话,应该就不用多说了) public static int getPrimes(int n) { List<Integer> list = new ArrayList<>(); for (int i = 2; i < n; i++) { boolean bool = true; for (int j = 2; j < i; j++) { if (i % j == 0) { bool = false; break; } } if (bool) { list.add(i); } } // System.out.println(list); return list.size(); }
带一些优化的暴力求质数
//带一些优化的暴力求质数 public static int getPrimes1(int n) { if (n < 3) { return 0; } //从3开始验算,所以初始值为1(2为质数)。 List<Integer> list = new ArrayList<>(); list.add(2); for (int i = 3; i < n; i++) { //当某个数为 2 的 n 次方时(n为自然数),其 & (n - 1) 所得值将等价于取余运算所得值 //*如果 x = 2^n ,则 x & (n - 1) == x % n //if(i % 2 == 0) if ((i & 1) == 0) { continue; } boolean bool = true; //用 j * j <= i 代替 j <= i 会更好。 //因为我们已经排除了所有偶数,所以每次循环加二将规避偶数会减少循环次数 for (int j = 3; j * j <= i; j += 2) { if (i % j == 0) { bool = false; break; } } if (bool) { list.add(i); } } // System.out.println(list); return list.size(); }
通过前面求得的质数对后面的质数进行判断
//通过前面求得的质数对后面的质数进行判断 public static int getPrimes2(int n) { //存放质数得list List<Integer> list = new ArrayList<>(); //求质数从2开始 for (int m = 2; m < n; m++) { //声明一个bool变量,看看是不是在list里面有能被整除得 boolean isPrime = true; //常见得求质数开平方 int sqrt = (int) Math.sqrt(m); //循环list,list里面都是求过得质数 for (Integer i : list) { //如果以前得质数能被n整除,说明n不是质数,false,list不能添加n //直接终止循环 if (m % i == 0) { isPrime = false; break; } //如果i大于当前这个数得开平方数,证明后面的已经不可能整除了 if (i > sqrt) { break; } } //如果当前循环内,没有被整除,即为质数,可以加入list,进行下一个循环 if (isPrime) { list.add(m); } } // System.out.println(list); return list.size(); }
厄拉多塞筛法
//厄拉多塞筛法 public static int getPrimes3(int n) { List<Integer> list = new ArrayList<>(); boolean[] bools = new boolean[n]; for (int i = 2; i < n; i++) { // 布尔类型的默认值为 假。所以在此处用了逻辑非(!)操作符。 if (!bools[i]) { list.add(i); for (int j = i + i; j < n; j += i) { //只要是i的倍数,就证明不是质数,因为他有其他因子 //排除不是质数的数 bools[j] = true; } } } // System.out.println(list); return list.size(); }
Bitmap对筛法的空间优化(主要是空间优化,当然也有效率优化)
/* Bitmap对筛法的空间优化(主要是空间优化,当然也有效率优化) 这个的意思就是signs是记录的第几层,每一层分为8个 也就是int为32字节,每个字节是8个bit (i & 31)==(i % 32) (1 << (i & 31))这一步是为了满足位数 signs[i / 32]是为了看第几层 ((signs[i / 32] & (1 << (i & 31))) == 0证明当前这一层的这一位并没有被记录 说明当前是个质数 循环: 循环中的j就是i的倍数,既然是倍数,就说明他不是质数 signs[j / 32] |= 1 << (j & 31); 在看这里,找到j的那一层,然后看j那一层那几位bit,如果有某一位有1存在,那这一位就是1 二进制下: 101 | 10 == 111 */ public static int getPrimes4(int n) { List<Integer> list = new ArrayList<>(); //一个 int 变量占用 32 字节 //如果是在C#中,提供了点阵列(BitArray)数组,那个的可读性会好很多 int[] signs = new int[n / 32 + 1]; for (int i = 2; i < n; i++) { //将元素和需确定得数字经行按位或运算,如果值改变,说明不存在该数字(未登记该数字),则其为质数。 //(当某个数为 2 的 n 次方时(n为自然数),其 & (n - 1) 所得值将等价于取余运算所得值) //*如果 x = 2^n ,则 x & (n - 1) == x % n //下面判断可以写成 //if ((signs[i / size] & (1 << (i % 32))) == 0) if ((signs[i / 32] & (1 << (i & 31))) == 0) { list.add(i); for (int j = i + i; j < n; j += i) { //登记该数字 signs[j / 32] |= 1 << (j & 31); } } } // System.out.println(list); return list.size(); }
最后来看一下各个求质数方法的效果图(这里用的是一百万以内的质数)
这里附上全部代码
import java.util.ArrayList; import java.util.List; public class Primes { public static void main(String[] args) { long start = System.currentTimeMillis(); System.out.println(getPrimes(1000000)); long end = System.currentTimeMillis(); System.out.println("最基础的暴力求质数" + (end - start) + "毫秒"); start = System.currentTimeMillis(); System.out.println(getPrimes1(1000000)); end = System.currentTimeMillis(); System.out.println("带一些优化的暴力求质数" + (end - start) + "毫秒"); start = System.currentTimeMillis(); System.out.println(getPrimes2(1000000)); end = System.currentTimeMillis(); System.out.println("通过前面求得的质数对后面的质数进行判断" + (end - start) + "毫秒"); start = System.currentTimeMillis(); System.out.println(getPrimes3(1000000)); end = System.currentTimeMillis(); System.out.println("厄拉多塞筛法" + (end - start) + "毫秒"); start = System.currentTimeMillis(); System.out.println(getPrimes4(1000000)); end = System.currentTimeMillis(); System.out.println("Bitmap对筛法的空间优化(主要是空间优化,当然也有效率优化)" + (end - start) + "毫秒"); } //最基础的暴力求质数 public static int getPrimes(int n) { List<Integer> list = new ArrayList<>(); for (int i = 2; i < n; i++) { boolean bool = true; for (int j = 2; j < i; j++) { if (i % j == 0) { bool = false; break; } } if (bool) { list.add(i); } } // System.out.println(list); return list.size(); } //带一些优化的暴力求质数 public static int getPrimes1(int n) { if (n < 3) { return 0; } //从3开始验算,所以初始值为1(2为质数)。 List<Integer> list = new ArrayList<>(); list.add(2); for (int i = 3; i < n; i++) { //当某个数为 2 的 n 次方时(n为自然数),其 & (n - 1) 所得值将等价于取余运算所得值 //*如果 x = 2^n ,则 x & (n - 1) == x % n //if(i % 2 == 0) if ((i & 1) == 0) { continue; } boolean bool = true; //用 j * j <= i 代替 j <= i 会更好。 //因为我们已经排除了所有偶数,所以每次循环加二将规避偶数会减少循环次数 for (int j = 3; j * j <= i; j += 2) { if (i % j == 0) { bool = false; break; } } if (bool) { list.add(i); } } // System.out.println(list); return list.size(); } //通过前面求得的质数对后面的质数进行判断 public static int getPrimes2(int n) { //存放质数得list List<Integer> list = new ArrayList<>(); //求质数从2开始 for (int m = 2; m < n; m++) { //声明一个bool变量,看看是不是在list里面有能被整除得 boolean isPrime = true; //常见得求质数开平方 int sqrt = (int) Math.sqrt(m); //循环list,list里面都是求过得质数 for (Integer i : list) { //如果以前得质数能被n整除,说明n不是质数,false,list不能添加n //直接终止循环 if (m % i == 0) { isPrime = false; break; } //如果i大于当前这个数得开平方数,证明后面的已经不可能整除了 if (i > sqrt) { break; } } //如果当前循环内,没有被整除,即为质数,可以加入list,进行下一个循环 if (isPrime) { list.add(m); } } // System.out.println(list); return list.size(); } //厄拉多塞筛法 public static int getPrimes3(int n) { List<Integer> list = new ArrayList<>(); boolean[] bools = new boolean[n]; for (int i = 2; i < n; i++) { // 布尔类型的默认值为 假。所以在此处用了逻辑非(!)操作符。 if (!bools[i]) { list.add(i); for (int j = i + i; j < n; j += i) { //只要是i的倍数,就证明不是质数,因为他有其他因子 //排除不是质数的数 bools[j] = true; } } } // System.out.println(list); return list.size(); } /* Bitmap对筛法的空间优化(主要是空间优化,当然也有效率优化) 这个的意思就是signs是记录的第几层,每一层分为8个 也就是int为32字节,每个字节是8个bit (i & 31)==(i % 32) (1 << (i & 31))这一步是为了满足位数 signs[i / 32]是为了看第几层 ((signs[i / 32] & (1 << (i & 31))) == 0证明当前这一层的这一位并没有被记录 说明当前是个质数 循环: 循环中的j就是i的倍数,既然是倍数,就说明他不是质数 signs[j / 32] |= 1 << (j & 31); 在看这里,找到j的那一层,然后看j那一层那几位bit,如果有某一位有1存在,那这一位就是1 二进制下: 101 | 10 == 111 */ public static int getPrimes4(int n) { List<Integer> list = new ArrayList<>(); //一个 int 变量占用 32 字节 //如果是在C#中,提供了点阵列(BitArray)数组,那个的可读性会好很多 int[] signs = new int[n / 32 + 1]; for (int i = 2; i < n; i++) { //将元素和需确定得数字经行按位或运算,如果值改变,说明不存在该数字(未登记该数字),则其为质数。 //(当某个数为 2 的 n 次方时(n为自然数),其 & (n - 1) 所得值将等价于取余运算所得值) //*如果 x = 2^n ,则 x & (n - 1) == x % n //下面判断可以写成 //if ((signs[i / size] & (1 << (i % 32))) == 0) if ((signs[i / 32] & (1 << (i & 31))) == 0) { list.add(i); for (int j = i + i; j < n; j += i) { //登记该数字 signs[j / 32] |= 1 << (j & 31); } } } // System.out.println(list); return list.size(); } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算