Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >判断一个数是不是素数

判断一个数是不是素数

作者头像
恋喵大鲤鱼
发布于 2020-12-08 01:55:29
发布于 2020-12-08 01:55:29
2.3K00
代码可运行
举报
文章被收录于专栏:C/C++基础C/C++基础
运行总次数:0
代码可运行

1.素数的定义

素数又名质数,指除了 1 和本身外不再有其他因数的自然数。

特别规定 0 和 1 既不是质数也不是合数。最小的质数是 2,最小的合数是 4。

下面给出常见判断方法,效率依次提升,以 Golang 为例给出实现。

2.直接法

给定数 n(n>2),根据质数的定义,很容易想到遍历 [2,n-1] 看是否存在某个数可以整除它,如果存在则不是素数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// isPrime 判断某个数是否是素数
func isPrime(n uint64) bool {
	if n <= 2 {
		return n == 2
	}
	for i := uint64(2); i < n; i++ {
		if n%i == 0 {
			return false
		}
	}
	return true
}

这里特殊处理不大于 2 的数,因为遍历 [2,n-1] 需要 n>2。

算法时间复杂度为 O(n),是最慢的实现。

3.初步优化

假如 n 是合数,必然存在非 1 的两个约数 p1 和 p2,其中p1<=sqrt(n),p2>=sqrt(n)。由此我们可以改进上述方法优化循环次数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func isPrime(n uint64) bool {
	if n <= 2 {
		return n == 2
	}
	sqrt := math.Sqrt(float64(n))
	for i := uint64(2); i <= uint64(sqrt); i++ {
		if n%i == 0 {
			return false
		}
	}
	return true
}

算法时间复杂度为 O(sqrt(n))。

4.继续优化

继续分析,其实质数还有一个特点,除了 2 和 3,它总是等于 6x-1 或者 6x+1,其中 x 是大于等于1的自然数。

上面的结论证明如下: (1)6x 能被 6 整除; (2)6x+2 能被 2 整除; (3)6x+3 能被 3 整除; (4)6x+4 能被 2 整除。 那么,就只有 6x+1 和 6x+5 (即等同于6x-1) 可能是质数了。

又因为合数有个性质,合数肯定有一个小于或等于根号的质因数,所以如果 n 能被 6 倍数两侧的数(才有可能是质数)整除,那么 n 是合数,否则 n 是素数。所以循环的步长可以设为 6,然后每次只判断 6 两侧的数能否整除 n 即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func isPrime(n uint64) bool {
	if n < 5 {
		return n == 2 || n == 3
	}
	// 不在6的倍数两侧的一定不是质数
	if n%6 != 1 && n%6 != 5 {
		return false
	}
	sqrt := math.Sqrt(float64(n))
	for i := uint64(5); i <= uint64(sqrt); i += 6 {
		// 是否是合数
		if n%i == 0 || n%(i+2) == 0 {
			return false
		}
	}
	return true
}

算法时间复杂度为 O(sqrt(n)/6)。

5.Miller-Rabin 概率素性测试算法

尽管上面的 O(sqrt(n)/6) 的算法已经非常优秀了,但是面对更高数量级的“大数”却会显得力不从心,所以上面朴素简单的算法一般不会用于工程实践中,一般使用 Miller-Rabin 算法。

Miller-Rabin 的理论基础来源于费马小定理,利用随机化算法判断一个数是合数还是可能是素数。关于 Miller-Rabin 算法原理这里不详细展开。

Golang 标准库基于 Miller-Rabin 已经实现了素性判断的方法,下面看下如何使用。

对于小于 2^64 的数,可以使用 big.ProbablyPrime(0),这种素性测试是100%准确的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const n = 1212121
if big.NewInt(n).ProbablyPrime(0) {
    fmt.Println(n, "is prime")
} else {
    fmt.Println(n, "is not prime")
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1212121 is prime

对于较大的数字,需要为 ProbablyPrime(n) 提供所需数量的测试 。对于 n 次测试,对于随机选择的非素数,返回 true 的概率最多为 (1/4)^n。一个常见的选择是使用 n = 20,这时误判概性率约为 0.000,000,000,001,基本可以认为是准确的了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
z := new(big.Int)
fmt.Sscan("170141183460469231731687303715884105727", z)
if z.ProbablyPrime(20) {
    fmt.Println(z, "is probably prime")
} else {
    fmt.Println(z, "is not prime")
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
170141183460469231731687303715884105727 is probably prime

其时间复杂度上界为 O(klog2​(n)),其中 k 为检测的轮数。增大 k 可以提高 Miller-Rabin 算法的准确度。

另外 Solovay–Strassen 也是工程中使用的概率素性判断算法,还有确定性算法 AKS,可在在多项式时间之内,决定一个给定整数是素数或者合数,感兴趣的同学可以了解一下这两个算法。

参考文献

[1] CSDN.判断一个数是不是质数(素数),3种方式介绍 [2] 知乎.Go语言中检测一个数是否为素数

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/12/04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何用 Java 判断一个给定的数是不是素数
有关素数的定义:质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
HoneyMoose
2021/09/24
9390
如何用 Java 判断一个给定的数是不是素数
数论部分第一节:素数与素性测试【详解】
数论部分第一节:素数与素性测试     一个数是素数(也叫质数),当且仅当它的约数只有两个——1和它本身。规定这两个约数不能相同,因此1不是素数。对素数的研究属于数论范畴,你可以看到许多数学家没事就想出一些符合某种性质的素数并称它为某某某素数。整个数论几乎就围绕着整除和素数之类的词转过去转过来。对于写代码的人来说,素数比想像中的更重要,Google一下BigPrime或者big_prime你总会发现大堆大堆用到了素数常量的程序代码。平时没事时可以记一些素数下来以备急用。我会选一些好记的素数,比如4567,
Angel_Kitty
2018/04/09
1.2K0
数学--数论---P4718 Pollard-Rho算法 大数分解
MillerRabin算法是一种高效的质数判断方法。虽然是一种不确定的质数判断法,但是在选择多种底数的情况下,正确率是可以接受的。PollardRho是一个非常玄学的方式,用于在O(n1/4)的期望时间复杂度内计算合数n的某个非平凡因子。事实上算法导论给出的是O(p​),p是n的某个最小因子,满足pp与n/pn/p互质。但是这些都是期望,未必符合实际。但事实上PollardRho算法在实际环境中运行的相当不错。这里我们要写一个程序,对于每个数字检验是否是质数,是质数就输出Prime;如果不是质数,输出它最大的质因子是哪个
风骨散人Chiam
2020/11/06
6980
判断一个数是不是素数的几种方法,不断优化!!! 素数判定 HDU - 2012
这种题目应该算是比较基础的了,但是,越是基础的东西,越是要记得清楚明白,初学C的时候,看过这种问题,后来慢慢就不在意了,再次看到这个题目,依然感触颇深。
种花家的奋斗兔
2020/11/13
1.1K0
2020-09-20:如何判断一个数是质数?
2.费尔马素性测试法法。费马小定理:假如p是质数,a是整数,且a、p互质,那么a的(p-1)次方除以p的余数恒等于1,即:a^(p-1)≡1(mod p)。
福大大架构师每日一题
2020/09/20
8600
2020-09-20:如何判断一个数是质数?
素数检验---跨越2000年的人类智慧
原来早有耳闻的「米勒-拉宾检验」,可以认为是费马小定理的优化版,被广泛用于计算机判断某数是否为质数。…(虽然路径并不相同。AKS更像是对费马素性检验思路上的优化)
fliter
2024/02/05
2750
素数检验---跨越2000年的人类智慧
世界总决赛选手带你玩转数论 1——素数及素性检测
笔者曾获得 ICPC 2020 世界总决赛资格,ICPC 2020 亚洲区域总决赛第五名。
ACM算法日常
2021/06/16
8770
如何判断一个数是否为素数(判断一个数为素数)
如上图所示,数字12可以将每4个分成一组,一共3组;而数字11将每4个、每5个、每3个分成一组都无法全部分完,而有剩余,因此将数字11称为质数。
全栈程序员站长
2022/08/02
1.6K0
如何判断一个数是否为素数(判断一个数为素数)
练习10—素数判断
题目 编写一个判断素数的函数,在主函数输入一个整数,输出该数是否为素数的信息。 解题步骤 (1)函数思想; (2)素数定义; (3)变量定义; (4)接收用户输入; (5)判断输出; Java import java.util.Scanner; public class Demo { public static boolean isPrime(int input) { int n = (int) Math.sqrt(input); if (input =
攻城狮杰森
2022/06/03
2960
判断一个数是不是质数(素数),3种方式介绍
这里特殊处理了一下小于等于3的数,因为小于等于3的自然数只有2和3是质数。
全栈程序员站长
2022/07/21
4.9K0
面试官本想拿一道求素数搞我,但被我优雅的"回击"了
现在的面试官,是无数开发者的梦魇,能够吊打面试官的属实不多,因为大部分面试官真的有那么那几下子。但在面试中,我们这些小生存者不能全盘否定只能单点突破—从某个问题上让面试官眼前一亮。这不,今天就来分享来了。
bigsai
2020/12/17
4140
面试官本想拿一道求素数搞我,但被我优雅的"回击"了
java素数筛选法
判断是否为素数 对于一个任意一个正整数,如果它只能被自身或1整除,称其为素数,否则为合数。1比较特殊,既不是质数也不是合数。
lexingsen
2022/02/24
5740
java素数筛选法
数学--数论--随机算法--Pollard Rho 大数分解算法 (带输出版本)
RhoPollard Rho是一个著名的大数质因数分解算法,它的实现基于一个神奇的算法:MillerRabinMillerRabin素数测试。
风骨散人Chiam
2020/11/06
7490
c/c++补完计划(三): 素数统计
前言 统计所有小于非负整数 n 的质数的数量 这是一道leetcode简单级别的, 本来没啥说的, 然后我发现了欧拉筛选法. 常规方法 常规思路就是对每个数x进行检测, 用x除以2到根号x, 有一个可以整除, 就不是素数. 优点是连数组或者vector都不需要, 有一个算一个, 很节省空间. bool isPrime(int i) { for (int j = 2; j * j <= i; ++j) { if (i % j == 0)return false;
sean_yang
2020/07/22
3620
2020-09-22:已知两个数的最大公约数,如何...
2020-09-22:已知两个数的最大公约数和最小公倍数,并且这两个数不能是最大公约数和最小公倍数本身。如何判断这两个数是否存在?
福大大架构师每日一题
2020/09/22
7930
2020-09-22:已知两个数的最大公约数,如何...
使用Python实现RSA加密算法及详解RSA算法「建议收藏」
代码已经放上github : https://github.com/chroje/RSA
全栈程序员站长
2022/08/15
7.1K0
使用Python实现RSA加密算法及详解RSA算法「建议收藏」
判断一个数是否为素数的代码(判断10000以内的数是不是素数)
素数(也叫质数)的数学定义为:大于1的自然数中除了1和它本身外没有其他因数的整数,常见的素数有:2,3,5,7,11,13……等,判断一个数是不是素数经常作为考试题目。
全栈程序员站长
2022/08/01
1.2K0
判断一个数是否为素数的代码(判断10000以内的数是不是素数)
RSA简介(三)——寻找质数
  要生成RSA的密钥,第一步就是要寻找质数,本节专讲如何寻找质数。   我们的质数(又称素数)、合数一般是对正整数来讲,质数就是只有1和本身两个的正整数,合数至少有3个约数,而1既不是合数也不是质数。   质数有无穷多个,这个早在古希腊时期就被证明了,使用反证法很容易证明:假设质数只有有限多,分别为a1.....an,则a1*a1....*an+1大于所有的质数,却不以任何质数为约数,推出矛盾,从而假设错误。   在质数的分布上,有个定理: lim  ∏ (n)/(n/ln(n)) = 1   n→∞
窗户
2018/02/07
1.1K0
判断一个数是否为素数(质数) c语言[通俗易懂]
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数。最小的质数是2,它也是唯一的偶数质数。 原理:number 只需被 (2 ~ 根号下number)之间的每一个整数去除就可以了(包括 根号下number这个数)。如果 nummber不能被 (2 ~ 根号下number) 间任一整数整除,number 必定是素数
全栈程序员站长
2022/07/23
1.7K0
判断一个数是否为素数(质数) c语言[通俗易懂]
golang 刷leetcode 数学基础(1)素(质)数
此方法的问题在于许多不必要的计算,因此可以想到用空间换时间:筛选出来的素数的倍数都可以标记为合数
golangLeetcode
2022/08/02
2920
推荐阅读
相关推荐
如何用 Java 判断一个给定的数是不是素数
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验