你不知道的几种素数判断方法,由浅入深,详解。(附送程序员必读好书)
对你有帮助别忘了给我点个赞哦~
将近50本能让程序员进入大厂应该精读的神书,免费 送给大家!只需要关注文章底下的公众号即可获得
我们要判断素数,首先要知道素数的定义。
素数:质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。
知道了素数的定义,那么我们应该想一下,如何去判断一个数是否为素数?
一种思路是,我们在每次得到一个数后,都去计算,去尝试因式分解它,看它除了1和自身之外还有没有其他因子
另一种是,我们去查阅素数表,看这个数在不在素数表上。那我们就要先得到素数表。
以下除了第一种方法,第2~4种方法都是用第二种思路做的
当要判断的目标数很少时,第一种高效。但是当给定的目标数组很多,数也很大时。后面的思路配上高效的查找算法,显然更高效
方法1:暴力求解
1-1:稍微动动脑
思想:
根据素数的定义思考。素数是大于1的自然数,除了1和自身外,其他数都不是它的因子。
那我们就可以用一个循环,从2开始遍历到这个数减去1,如果这个数都不能被整除,那么这个数就是素数。
也就是说:
给定一个数 n , i 从 2 开始取值,直到 n - 1(取整数),如果 n % i != 0 , n 就是素数
进一步思考,有必要遍历到 n - 1 吗?
除了1以外,任何合数最小的因子就是2,那最大的因子就是 n/2
那我们就遍历到 n/2就足够了
这样我们就可以写出这个算法的核心代码:
int isPrime(int target) {int i = 0;if (target <= 1) {printf("illegal input!\n");//素数定义return -1;}for (i = 2; i <= target / 2; i++) {if (target % i == 0)return 0;//不是素数直接返回0}return 1;//是素数返回1
}
1-2:再进一步
思想:
在上面的基础上,其实不需要遍历到 n/2,只需要到 根号n(包含根号n) 就可以了。为什么呢?这是个数学问题,大家自行思考一下。
核心代码:
int isPrime(int target) {int i = 0;if (target <= 1) {printf("illegal input!\n");//素数定义return -1;}for (i = 2; i <= (int)sqrt(target); i++) {if (target % i == 0)return 0;}return 1;
}
从第二种方法开始,我们都是先完成判断素数数组,然后用二分法去查找判断数组
这里说一下以下三种方法牵扯的概念:
范围:1 ~ 范围上限N
范围上限N:判断素数需要用户输入随机素数,这个随机素数的范围是1 ~ N
判断素数数组:将数组的
下标
与1 ~ N
的自然数一一对应起来。
判断 1到N 的自然数是否为素数,其实就是判断数组的下标是否为素数,如果是 给这个下标所对应的判断素数数组元素赋1,否则赋0
比如:我要判断3是否为素数,我们就找到判断素数数组isPrime
中的下标为3的元素,即:isPrime[3]
如果3
是素数 , 赋值1,即isPrime[3] = 1
如果 3 不是素数,赋值0 ,即isPrime[3] = 0
这样我们在用二分法查找时,查找数组下标就可以,找到下标后返回下标对应的判断素数数组的值。
如果是1说明下标对应的自然数是素数,否则不是
方法2:用素数表来判断素数
思路:
如果一个数不能整除比它小的任何素数,那么这个数就是素数
这种“打印”素数表的方法效率很低,不推荐使用,可以学习思想
核心代码:
//target:输入的要查找的数
//count:当前已知的素数个数
//PrimeArray:存放素数的数组
int isPrime(int target, int count, int* PrimeArray) {int i = 0;for (i = 0; i < count; i++) {if (target % PrimeArray[i] == 0)return 0;}return 1;
}
方法3:普通筛法——埃拉托斯特尼(Eratosthenes)筛法
思路:
1. 我们的想法是,创建一个比范围上限大1的数组,我们只关注下标为 1 ~ N(要求的上限) 的数组元素与数组下标(一一对应)。
2. 将数组初始化为1。然后用for循环,遍历范围为:【2 ~ sqrt(N)】。如果数组元素为1,则说明这个数组元素的下标所对应的数是素数。
3. 随后我们将这个下标(除1以外)的整数倍所对应的数组元素全部置为0,也就是判断其为非素数。
这样,我们就知道了范围内(1 ~ 范围上限N)所有数是素数(下标对应的数组元素值为1)或不是素数(下标对应的数组元素值为0)
用百度百科对埃拉托斯特尼筛法简单描述:要得到自然数n以内的全部素数,必须把不大于 的所有素数的倍数剔除,剩下的就是素数。
核心代码:
// 判断素数的数组 范围上限N
void Eratprime(int* isprime, int upper_board) {int i = 0;int j = 0;//初始化isprimefor (i = 2; i <= upper_board; i++)isprime[i] = 1;for (i = 2; i < (int)sqrt(upper_board); i++) {if (isprime[i]) {isprime[i] = 1;}for (j = 2; i * j <= upper_board; j++) {//素数的n倍(n >= 2)不是素数isprime[i * j] = 0;}}}
方法4:线性筛法——欧拉筛法
思路:
我们再思考一下上面的埃拉托斯特尼筛法,会发现,在“剔除“非素数时,有些合数会重复赋值。这样就会增加复杂度,降低效率。
比如:范围上限N = 16时2是素数,剔除”2 的倍数“,它们是:4,6, 8,10, 12, 14, 16 3是素数,剔除”3 的倍数”,它们是,6,9,12,15
6,12是重复的。如何减少重复呢?
核心代码:
void PrimeList(int* Prime, bool* isPrime, int n) {int i = 0;int j = 0;int 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;}}}
}
如果你没有理解,可以参考下例
以上四种算法的完整代码在我的github上,帮助到你了不妨给我点个star哦~
本来文章到这了就结束了,但是考虑到特殊时期,各位同学在家应该待得有点无聊了,优秀的各位应该会充分利用时间,多看书,多学习。那么在下面推荐一些我往期的干货文章,希望对大家有帮助!
推荐阅读:
精选教学:
操作符详解(上)
那些关于函数我们容易忽略的基础知识
C语言:
C语言复习巩固(一)
C语言复习巩固(二)
C语言复习巩固(三)
C语言复习巩固(四) 函数
C语言复习巩固(五) 指针(初阶)
猜数字小游戏详解 如何用rand,srand,time来完成随机数发生
C语言游戏之扫雷
三子棋C语言实现
C++:
C++入门(一)
C++入门(二)
除此之外,我整理了将近50本学习 C/C++/linux/unix/网络/算法 必读的好书,在这里以电子书的形式免费送给各位未来的精英们。只需要关注我的公众号,后台回复:[好书] 即可获得网盘链接
最后,感谢大家的观看,有什么问题都可以在下方评论区评论或者公众号后台回复,看到我就会回复大家!
在这里祝各位健健康康过一个充实的假期!
感谢指出我错误的微信网友: 大异小同 。
本次修改内容:
1. 1-1中的代码,for循环的循环控制 i < target / 2 改为 i <= target
错误情况:当 target == 4 时,target / 2 的值是 2,i 从 2开始,如果 循环控制是:i < target / 2, 则不会进入 for 循环,所以会将 4 误判为素数
2. sqrt 函数的返回值是 double 类型。
将 i <= sqrt(target) 改为 i <= (int)sqrt(target)
sqrt 函数的函数原型:double sqrt(double arg);
2020 - 2 - 24 日修改:
你不知道的几种素数判断方法,由浅入深,详解。(附送程序员必读好书)相关推荐
- 史上最全 JVM 大全详解、java 程序员细节到极致的一次,魔鬼
前言 作为 Java 的从业者,在找工作的时候,一定会被问及关于 JVM 相关的知识. JVM 知识的掌握程度,在很多面试官眼里是候选人技术深度的一个重要评判标准.而大多数人可能没有对 JVM 的实际 ...
- 史上最全 JVM 大全详解!java 程序员细节到极致的一次,魔鬼
前言 作为 Java 的从业者,在找工作的时候,一定会被问及关于 JVM 相关的知识. JVM 知识的掌握程度,在很多面试官眼里是候选人技术深度的一个重要评判标准.而大多数人可能没有对 JVM 的实际 ...
- cat命令详解_好程序员Python培训之详解eval好与坏
好程序员Python培训之详解eval好与坏,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们一起来看一下吧. eval是Python的一个内置函数,这个函数的作用 ...
- “史上最全”Spring Boot详解!java程序员细节到极致的一次,魔鬼
这本书的灵感 当时公司的技术栈全面转入Spring Boot体系,源于本书作者在公司的一次分享会上的分享.当时作者用了不到10分钟就使用Spring Boot轻松制作了一个功能完整的数据增加.删除.修 ...
- python的sort方法是哪种_python中的sort方法使用详解
Python中的sort()方法用于数组排序,本文以实例形式对此加以详细说明: 一.基本形式列表有自己的sort方法,其对列表进行原址排序,既然是原址排序,那显然元组不可能拥有这种方法,因为元组是不可 ...
- mvc ajax提交html标签,Mvc提交表单的四种方法全程详解
Mvc提交表单的四种方法全程详解 2019-01-05 编程之家 https://www.jb51.cc 编程之家收集整理的这篇文章主要介绍了Mvc提交表单的四种方法全程详解,编程之家小编觉得挺不错的 ...
- 安卓判断服务器返回的状态码,关于服务器返回的十四种常见HTTP状态码详解
原标题:关于服务器返回的十四种常见HTTP状态码详解 HTTP状态码 状态码是由3位数字和原因短语组成的(比如最常见的:200 OK),其中第一位数字表示响应类别,响应类别从1到5分为五种 add:其 ...
- android 实现毫秒定时器,Android实现定时器的五种方法实例详解
一.Timer Timer是Android直接启动定时器的类,TimerTask是一个子线程,方便处理一些比较复杂耗时的功能逻辑,经常与handler结合使用. 跟handler自身实现的定时器相比, ...
- 设计模式——模版方法模式详解(论沉迷LOL对学生的危害)
0. 前言 写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦 ...
- golang导入git包_使用go module导入本地包的方法教程详解
go module 是Go1.11版本之后官方推出的版本管理工具,并且从 Go1.13 版本开始, go module 将是Go语言默认的依赖管理工具.到今天 Go1.14 版本推出之后 Go mod ...
最新文章
- IDOC 创建,增强,管理,配置
- CentOS各个版本国内镜像下载地址,下载速度10M+
- StoryBoard解惑
- 霍金一生重要时刻照片合集,3次来中国,年轻时也是帅哥一枚
- websocket没准备好如何解决_那些很重要,但是不常用的技术,websocket
- c语言高低位拷贝_C语言指针详解
- java异常没有catch住_今天才真正了解Java的异常处理
- 谷歌悄悄修复4个 0day
- linux系统yum提示注册,Linux:redhat6.5使用yum时提示需要注册问题解决方案
- 唧唧Down(B站视频下载) 彻底解决你的B站视频下载问题
- 如何在arcgis中制作土地利用转移矩阵
- 【026】国务院督查组莅临翼辉信息参观调研
- win10退出微软账号
- 正在保存备份的驱动器与启动计算机,如何创建和使用Dell Recovery Restore USB驱动器...
- 最近很多人问我:saiku下载不下来
- 互联网早报:腾讯推出“电子签平台” 用微信就能开出具备法律效力的电子收据
- C语言——任意分数化简
- 【java基础面试题】
- 地方门户网站SEO 重点做长尾词
- 论文阅读笔记(五)CLIP4Clip: An Empirical Study of CLIP for End to End Video Clip Retrieval
热门文章
- 又一程序员猝死...
- apple开发者账号区别
- 香港服务器低价租用内幕
- 嵌入式平台 STM32 libqrencode 移植 二维码生成
- C++(35)——判断一个数能否同时被3和5整除
- 【Python实例学习】用Python的xlsxwriter模块,进行Excel表格插入图标的操作
- matlab 简单算例,MATLAB 3D 动画简单实例 | 学步园
- rancher部署安装好后,无法部署pod
- 2019级软件工程应用与实践-人工智能快递柜(代码分析9)
- 啥?学习微服务,你竟然不知道什么是熔断,降级和限流