素数判断的五种方法

素数判断是我们写程序过程中经常遇见的一个问题,于是今天我简单地整理一下常用的素数判断的方法。

素数的介绍

素数定义

质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数;否则称为合数。

根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积;而且如果不考虑这些质数在乘积中的顺序,那么写出来的形式是唯一的。最小的质数是2。
                        --------360百科

第一种:暴力筛选法

思路分析

根据素数的定义,我们可以简单地想到:若要判断n是不是素数,我们可以直接写一个循环(i从2到n-1,进行n%i运算,即n能不能被i整除,如被整除即不是素数。若所有的i都不能整除,n即为素数)。

代码实现

boolean isPrime(int n){for(int i=2;i<n;i++){//如果n被i整除,则返回falseif(n%i==0){return false;break;}}return true;    // 反之则返回true
}

时间复杂度:O(n)

这时间复杂度一看就不咋乐观,于是我们简单优化一下。

boolean isPrime(int n){for ( i=2; i<=(int)sqrt(n); i++ ){//如果n被i整除,则返回falseif(n%i==0){return false;break;}}return true;    // 反之则返回true
}

时间复杂度:O(sqrt(n))

优化原理:素数是因子为1和本身, 如果num不是素数,则还有其他因子,其中的因子,假如为a,b.其中必有一个大于sqrt(num) ,一个小于sqrt(num) 。所以必有一个小于或等于其平方根的因数,那么验证素数时就只需要验证到其平方根就可以了。即一个合数一定含有小于它平方根的质因子。

第二种:素数表筛选法

素数表筛选法一看名字就知道是将素数存到一个表中,然后对需要判断的数在表中查找,找了就是素数,找不到的即不是素数。

思路分析

如果一个数不能整除比它小的任何素数,那么这个数就是素数

顺便嘀咕一句,这种方法的效率贼低,看看就好,学习一下思路就行。

代码实现

/*target:要查询的数字count:素数表中素数的个数PrimeArray:素数表数组
*/
boolean isPrime(int target, int count, int[] PrimeArray){for (i = 0; i < count; i++){if (target % PrimeArray[i] == 0){return false;break;}}return true;
}

时间复杂度:O(n)

第三种:埃拉托斯特尼(Eratosthenes)筛法

思路分析

创建一个比范围上限大1的数组,我们只关注下标为 1 ~ N(要求的上限) 的数组元素与数组下标对应。
将数组初始化为1。然后用for循环,遍历范围为:[2 ~ sqrt(N)]。如果数组元素为1,则说明这个数组元素的下标所对应的数是素数。
随后我们将这个下标(除1以外)的整数倍所对应的数组元素全部置为0,也就是判断其为非素数。
这样,我们就知道了范围内(1 ~ 范围上限N)所有数是素数(下标对应的数组元素值为1)或不是素数(下标对应的数组元素值为0)

例子(N=25)

详细列出算法如下:
1、列出2以后的所有序列:
 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
2、标出序列中的第一个素数,也就是2,序列变成:
 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
3、将剩下序列中,划掉2的倍数,序列变成:
 2 3 5 7 9 11 13 15 17 19 21 23 25
4、如果这个序列中最大数小于最后一个标出的素数的平方,那么剩下的序列中所有的数都是素数,否则回到第二步。
5、本例中,因为25大于2的平方,我们返回第二步:
6、剩下的序列中第一个素数是3,将主序列中3的倍数划掉,主序列变成:
 2 3 5 7 11 13 17 19 23 25
7、我们得到的素数有:2,3
8、25仍然大于3的平方,所以我们还要返回第二步:
9、序列中第一个素数是5,同样将序列中5的倍数划掉,主序列成:
 2 3 5 7 11 13 17 19 23
10、我们得到的素数有:2,3,5 。
11、因为23小于5的平方,跳出循环。

结论:2到25之间的素数是:2 3 5 7 11 13 17 19 23。

代码实现

/*target:要查询的数字isprime:素数数组,大小至少为n+1n:数值上界
*/
boolean isPrime(int target,int[] isprime, int n){isprime[2]=0;int k=2,tt=0;while(tt<n+1){for(int i=1; i<isprime.length; i++){ //将不是素数的数筛出if(i%k==0&&i!=k) isprime[i]=1;}for(int i=1; i<isprime.length; i++){ //将筛选后的第一个数当做新的筛子if(i>k&&isprime[i]==0){k=i;break;}}tt++;}if(isprime[target]==1)return  true;else return false;
}

时间复杂度:O(n^3)

第四种:线性筛选–欧拉筛法

思路分析

在埃拉托斯特尼(Eratosthenes)筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。

代码实现

void PrimeList(int* Prime, bool* isPrime, int n) {int i = 0, j = 0, count = 0;if (isPrime != NULL) {//确保isPrime不是空指针//将isPrime数组初始化为 1for (i = 2; i <= N; i++) {isPrime[i] = true;}}if (isPrime != NULL && Prime != NULL) {//从2遍历到范围上限Nfor (i = 2; i <= N; i++) {if (isPrime[i])//如果下标(下标对应着1 ~ 范围上限N)对应的isPrime值没有被置为false,说明这个数是素数,将下标放入素数数组Prime[count++] = i;//循环控制表达式的意义:j小于等于素数数组的个数 或 素数数组中的每一个素数与 i 的积小于范围上限Nfor (j = 0; (j < count) && (Prime[j] * (long long)i) <= N; j++)//将i强制转换是因为vs上有warning,要求转换为宽类型防止算术溢出。数据上不产生影响{isPrime[i * Prime[j]] = false;//每一个素数的 i 倍(i >= 2)都不是素数,置为false//这个是欧拉筛法的核心,它可以减少非素数置false的重复率//意义是将每一个合数(非素数)拆成 2(最小因数)与最大因数 的乘积if (i % Prime[j] == 0)break;}}}
}

时间复杂度:O(n)

第五种:欧拉筛法优化

由上面欧拉筛法的代码可见,欧拉筛法的代码也挺臃肿的,于是我们简单优化一下。

代码实现

boolean isPrime(int num) {if (num <= 3) {return num > 1;}// 不在6的倍数两侧的一定不是质数if (num % 6 != 1 && num % 6 != 5) {return false;}int sqrt = (int) Math.sqrt(num);for (int i = 5; i <= sqrt; i += 6) {if (num % i == 0 || num % (i + 2) == 0) {return false;}}return true;
}

结束语

本文部分参考以下文章:
https://zhuanlan.zhihu.com/p/104314640

如有问题,欢迎留言交流,共同进步

素数(质数)判断的五种方法相关推荐

  1. 素数判断的几种方法代码实现及其复杂度分析

     素数判断的几种方法代码实现及其复杂度分析  原文链接:http://blog.csdn.net/infinitezhen/article/details/8961964 一. 朴素判断素数 根据素数 ...

  2. 3.js中判断数组中是否存在某个对象/值,判断数组里的对象是否存在某个值 的五种方法 及应用场景|判断数组里有没有某对象,有不添加,没有则添加到数组

    3.js中判断数组中是否存在某个对象/值,判断数组里的对象是否存在某个值 的五种方法 及应用场景 一.当数组中的数据是简单类型时: 应用js中的indexof方法:存在则返回当前项索引,不存在则返回 ...

  3. php判断数组的值是否为空,PHP判断数组是否为空的常用方法(五种方法)

    本文介绍了PHP开发中遇到的数组问题,小编在这里给大家总结了5中方法关于php判断数组是否为空问题,需要的朋友参考下 本文介绍了PHP开发中遇到的数组问题,这里介绍了判断PHP数组为空的5种方法,有需 ...

  4. Qt-窗口消息处理机制及拦截消息的五种方法

    [Qt 拦截消息的五种方法] 覆写框架类QCoreApplication的notify函数,这个函数将得到整个框架中所有窗口的消息 给框架类安装一个消息过滤器 QCoreApplication-> ...

  5. 手机断触怎么办_手机触摸屏失灵了怎么办,五种方法自己就能修好它!

    点击"蓝字"关注我们 ○ ○ 做 优 品 · 创 名 品 欧仕极 手机触摸屏常见问题排查 01 触摸屏断触 我们在点击某个图标时,正常情况下,手机会有所反应(一般按键底色变灰),反 ...

  6. html转pdf(总结五种方法Java)

    html转pdf(总结五种方法Java) Java 实现html转pdf,总结五种方法. 推荐使用wkhtmltopdf,Itext 方法一:使用wkhtmltopdf 1.下载插件wkhtmltop ...

  7. 【SSL1759】连通分量【五种方法】

    Description 求一个图的连通分量 Input n 顶点数(<=100) 连接的边 Output 连通分量 Sample Input 8 6 3 1 2 2 5 5 4 4 1 8 7 ...

  8. Linux:检查当前运行级别的五种方法

    2019独角兽企业重金招聘Python工程师标准>>> 运行级就是Linux操作系统当前正在运行的功能级别.存在七个运行级别,编号从0到6.系统可以引导到任何给定的运行级别.运行级别 ...

  9. python 重载_python模块重载的五种方法

    环境准备 新建一个 foo 文件夹,其下包含一个 bar.py 文件 bar.py 的内容非常简单,只写了个 print 语句 只要 bar.py 被导入一次,就被执行一次 print 禁止重复导入 ...

最新文章

  1. DOM---文档对象模型(Document Object Model)的基本使用
  2. Java解压zip文件(文本)压缩包
  3. linux脚本石英钟,原生JS实现的简单小钟表功能示例
  4. 2017-2018-1 20155320 《信息安全系统设计基础》第十四周学习总结
  5. Table '' is marked as crashed and should be repaired 解决方法
  6. Golang 入门笔记(一)
  7. idea开发swing项目_IntelliJ IDEA 开发swing(一)
  8. CentOS7虚拟机搭建xwiki
  9. android makefile文件批量拷贝文件的方法
  10. 汇编语言和本地代码及通过编译器输出汇编语言的源代码
  11. 基于 CEEMDAN 和小波包的降噪方法研究
  12. Bayes‘ theorem贝叶斯定理(基础理论+心理学小例子)
  13. STM32旋转立方体
  14. 蓝桥杯—切面条/大衍数列
  15. 基于MATLAB金属表面缺陷分类与测量的GUI设计
  16. JAVA中webSockt一对一聊天
  17. Boundary Smoothing for NER
  18. 【国家集训队2011】【BZOJ2141】排队
  19. 使用qemu运行银河麒麟操作系统
  20. IT 2018总结:足迹第五十三步我的同学网聊收获(好口才的十一条铁则)

热门文章

  1. 产品经理认证NPDP考试心得
  2. 如何使用SP页面生成器插件从一个Joomla模板到另一个
  3. 华为校园实习生招聘总结与感悟
  4. 【论文速递】ECCV2022 - 密集高斯过程的小样本语义分割
  5. Arduino uno 宿舍NFC开门方案
  6. android app性能测试工具,Android 性能测试 - 内存
  7. Unity Android接入Adtming广告聚合平台
  8. ionic4本地通知Local Notifications
  9. android 屏幕dp值计算
  10. 度量两个矩阵的相似性