文章目录

  • 1.素数的定义
  • 2.直接法
  • 3.初步优化
  • 4.继续优化
  • 5.Miller-Rabin 概率素性测试算法
  • 参考文献

1.素数的定义

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

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

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

2.直接法

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

// 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)。由此我们可以改进上述方法优化循环次数。

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 即可。

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%准确的。

const n = 1212121
if big.NewInt(n).ProbablyPrime(0) {fmt.Println(n, "is prime")
} else {fmt.Println(n, "is not prime")
}

输出:

1212121 is prime

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

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")
}

输出:

170141183460469231731687303715884105727 is probably prime

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

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

参考文献

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

判断一个数是不是素数相关推荐

  1. C语言试题六十九之请编写函数判断一个数是不是素数

    1. 题目 编写函数:判断一个数是不是素数 素数:素数又称质数.所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除. 2 .温馨提示 ...

  2. 用户输入的数是否为合数php,php怎么判断一个数是不是素数?

    质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数.(注:1不是素数.)那么php怎么判断一个数是不是素数?下面本篇文章就来给大家介绍一下. 下面我们就 ...

  3. js中如何判断一个数是不是素数(三种方法)

    素数:又叫质数,在大于1的自然数中,除了1和它本身以外不再有其他因数.即只能被1和它本身整除的数就是素数 这是作为编程入门时,经常会做的一道题. <!DOCTYPE html> <h ...

  4. 用Java编写2到100之间的素数;判断一个数是不是素数

    目录 1.用Java编写2到100之间的素数 2.判断一个数是不是素数 1.用Java编写2到100之间的素数 package day_2023_4_18;public class Main {pub ...

  5. 请编写函数判断一个数是不是素数

    1. 题目 编写函数:判断一个数是不是素数 素数:素数又称质数.所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除. 2 .温馨提示 ...

  6. 用C语言实现一个函数,判断一个数是不是素数

    用C语言实现一个函数,判断一个数是不是素数 编写程序,设计一个函数IsPrime,该函数用于判定一个数m是否是素数,如果是素数则返回1,否则返回0. 素数定义:只能被1和本身整除而不能被他其他正整数整 ...

  7. c语言判断一个数是不是质数的n次方,c语言实践 判断一个数是不是素数

    int main() { int input = 0; scanf_s("%d",&input); if (input < 2) { printf("wro ...

  8. java 判断一个数是不是素数

    1.素数就是只能被1和自身整除的数(任何数都能被1整除,这里就不做过多解说了) 2.分析:输入一个数判断是不是素数 比如:7 这里可以写一个循环,除了7以外判断一下其他小于7的数能不能被整除,如果还能 ...

  9. Java 求1-100以内的所有素数,判断一个数是不是素数。Java代码实现附测试结果图

    质数(prime number)又称素数,有无限个. 质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数的数称为质数. 小师弟问了我个这么个联系题,虽然看似简单,但是,大家都觉得简单的东西 ...

  10. C++ 判断一个数是不是素数

    题目:判断一个数是不是素数,1 < N <= 50000 思路:判断n是否整除(求余是否等于0)大于1而小于sqrt(n)中的任何一个数,如果有则不是素数,否则是素数 实现代码: // 判 ...

最新文章

  1. 不得不提的团队协作工具
  2. linq to sql初步
  3. 线程属性--十分重要的概念
  4. map按value值查找——find_if的使用(转载)
  5. activity7 拖不动_Activiti7相关问题汇总
  6. 腾讯开源负责人许勇:未来开源计划重点是AI和服务小程序生态
  7. Linux中的MAN命令
  8. cobbler安装4个报错汇总及解决方法:ImportError
  9. 系统学习 TypeScript(四)——变量声明的初步学习
  10. 第一季度VR市场报告出炉,中国市场份额下降至全球第三
  11. PPT(二)-让您的幻灯片“炫”起来!
  12. python图像风格迁移教程_【人工智能】python图像风格迁移,来欣赏梵高风格的石原里美吧!...
  13. C51单片机数码管显示数字实现
  14. U盘装系统中bios怎么设置USB启动(图文教程)
  15. Predicting human microbe–disease associations via graph attention networks with inductive matrix论文解析
  16. 跟未名学Office - PPT操作:高效
  17. 详情页用虚拟机还是云服务器,详情页用虚拟机还是云服务器
  18. 常用的进制之间相互转换
  19. 二十九岁,刚读完了财富启蒙读物《小狗钱钱》
  20. 直播--android端推流实现一

热门文章

  1. Oracle JDK各版本下载汇总
  2. 【Java】UML类图详解-详细易懂
  3. poi动态合并内容相同的单元格
  4. linux卸载 bind,Linux CentOS中 BT下载客户端 安装及卸载方法 Transmission
  5. matlab:使用改进欧拉法,求解微分方程
  6. JavaScript 根据经纬度得出中心点的经纬度
  7. 云原生虚拟化:一文读懂网络虚拟化之 tun/tap 网络设备
  8. 声卡自动修补appleHDA,支持AMD平台
  9. 个人信息安全防护指南!
  10. Python 函数绘图及函数图像微分与积分