素数判定的优化

常规写法亲民,高效写法炼人。用素数的基本特性写,易读易懂;用6k±1特性写,高效但却得有学过《数论》。


(笔记模板由python脚本于2024年05月09日 19:47:00创建,本篇笔记适合初通Python,熟悉六大基本数据(str字符串、int整型、float浮点型、list列表、tuple元组、set集合、dict字典)的coder翻阅)


【学习的细节是欢悦的历程】

  • Python 官网:https://www.python.org/

  • Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简单……
    地址:https://lqpybook.readthedocs.io/


  自学并不是什么神秘的东西,一个人一辈子自学的时间总是比在学校学习的时间长,没有老师的时候总是比有老师的时候多。
            —— 华罗庚


  • My CSDN主页、My HOT博、My Python 学习个人备忘录
  • 好文力荐、 老齐教室
等风来,不如追风去……


常规写法亲民
素数判定的优化
(高效写法炼人)


本文质量分:

96 96 96

本文地址: https://blog.csdn.net/m0_57158496/

CSDN质量分查询入口:http://www.csdn.net/qc


目 录

  • ◆ 素数判定的优化
    • 0、“高级”代码
    • 1、最平民的写法
    • 2、算法优化
      • 2.1 剔除偶数
      • 2.2 平方根特性
      • 2.3 6k±1规则
      • 2.4 素数列表
      • 2.5 代码解析
    • 3、结语
    • 4、我关于“素数”的学习笔记
    • 5、完整源码(Python)


◆ 素数判定的优化


0、“高级”代码


  • ‘高效的素数判定算法’
    在这里插入图片描述
      当我读懂这段代码的时候(这是一个非法高效的算法,找出106以内的所有素数,用时不到6秒),就有些感叹了。解决“问题”的代码也和写文章的词句一样,也是要“推敲”的,在不同的语境表达不一样的“情感”。所以,有了这篇笔记。😋



回页目录


1、最平民的写法


  素数是一个大于1的自然数,除了1和它本身以外不再有其他因数。换句话说,如果一个数只能被1和它本身整除,那么这个数就是素数。例如,2、3、5、7、11、13、17、19、23等都是素数。


  根据素数的定义可以写法判断素数的基本算法。 这是最简单直接的方法。对于给定的数n,如果n不是2,则检查从2到n的所有整数是否能整除n。如果能被整除,则n不是素数;如果都不能整除,则n是素数。


python代码


def isPrime(num: int) -> bool:''' 素数判定 '''if num < 2:return False # 小于2的都不是素数for i in range(2, num):if num%i == 0:return False # 当num有1和自身以外的因子,不是素数return True # 经过前面的排查,就只剩素数了

  • 效率
    在这里插入图片描述


回页目录


2、算法优化


2.1 剔除偶数


  除2之外,偶数都不是素数。据此特性,可以首先剔除偶数,减少试除次数而增效。


Python代码


def isPrime(num: int) -> bool:''' 素数判定 '''if num < 2:return False # 小于2的都不是素数if num == 2: return True # 2是素数elif num%2 == 0: return False # 剔除偶数for i in range(3, num, 2): # 只试除大于2的奇数if num%i == 0:return False # 当num有1和自身以外的因子,不是素数return True # 经过前面的排查,就只剩素数了

  • 效率
    在这里插入图片描述
    减少了一半试除,增效一倍。



回页目录


2.2 平方根特性


  一个自然数的因子,必定不大于其平方根。因为如果自然数n有一个因子大于sqrt(n),那么必定有一个因子小于sqrt(n)。
据此,可以优化算法,提升效率。


Python代码


def isPrime(num: int) -> bool:''' 素数判定 '''if num < 2:return False # 小于2的都不是素数for i in range(2, num):if i*i > num: break # 一个数的因子,必定小于等于其平方根if num%i == 0:return False # 当num有1和自身以外的因子,不是素数return True # 经过前面的排查,就只剩素数了

  • 效率
    在这里插入图片描述
    减少了试除的一半(当被判定的数是素数时),次数效率提升了近50倍。



回页目录


2.3 6k±1规则


  所有的素数除了2和3都形如6k±1的形式,其中k是非负整数。这个规则可以减少试除法中需要检查的数的数量。


Python代码


def isPrime(num: int) -> bool:''' 素数判定 '''if num < 2:return False # 小于2的都不是素数if num == 2 or num == 3: return True # 2和3都是素数elif num%2 == 0 or num%3 == 0: return False # 剔除2、3的倍数for i in range(5, int(num**0.5)+1, 6): # 只检查6k±1的自然数if num%i == 0 or num%(i+2) == 0:  return False # 大于5的素数都满足6k±1的形式,6k形式的数一定是合数return True # 经过前面的排查,就只剩素数了

  • 效率
    在这里插入图片描述
    在这里插入图片描述
    这即是,开篇图片中的“最佳算法”。



回页目录


2.4 素数列表


  找出限定范围内的所有素数,如果有上限平方根以内的素数列表,+上6k±1规则,可以更高效的“运作”。如查找106以内的所有素数:


Python代码


def isPrime(num: int) -> bool:if num > 10**6-1:input(f"\n{' 本函数仅限于查找10^6以内的素数 ':~^28}")return # 退出代码执行返回命令行if num < 2:return False # 剔除2以下的数if 1 < num < 4:return Trueif num%2 == 0 or num%3 == 0:return Falsemyprimes = (5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997) # 1000以内大于5的素数,由于前面已剔除2、3的倍数,就不再试除2、3。本列表仅限于查找100w以内的素数myprimes = iter(myprimes)for i in myprimes:if i*i > num:break if num%i == 0:return Falsereturn True#isPrime(1000_000+1) # 调试报错提示

  • 效率
    在这里插入图片描述
      由试炼可鉴,用时比6k±1规则又缩短了近1/4。

  • 报错提示调试
    在这里插入图片描述



回页目录


2.5 代码解析


  • 对2.3节代码的评价
    1行:函数定义,接受一个整数参数 num,并返回一个布尔值。
    2行:函数的文档字符串,简要描述了函数的功能。
    4行:如果 num 小于2,直接返回 False,因为素数定义为大于1的自然数。
    6-7行:如果 num 等于2或3,直接返回 True,因为2和3都是素数。
    9行:如果 num 是2或3的倍数,返回 False,因为这些数都是合数。
    11行:这里开始了一个 for 循环,循环的范围是从5到 int(num**0.5)+1,步长为6。这个循环的设计是高效的,因为它只检查了可能是素数的一部分数字。所有大于3的素数都可以表示为6k±1的形式,其中k是自然数,因为所有形如6k的数都可以被2和3整除,所以不可能是素数。
    12-13行:在循环内部,检查 num 是否能被 ii+2 整除。如果能,那么 num 不是素数,返回 False。
    15行:如果循环结束都没有找到能整除 num 的数,那么 num 是素数,返回 True。

      总体来说,这段代码是高效的,因为它避免了不必要的检查,并且利用了素数的性质来减少计算量。这种方法的效率很高,尤其是对于较大的数。代码的逻辑清晰,注释也很好地解释了每一步的目的。这是一个很好的素数判定函数的实现。

  • 对2.4节代码的解析
    1-4行:首先检查输入的数值是否超过函数的处理范围(10^6 - 1)。如果是,则打印一条消息并退出函数,返回 None。这里使用了一个格式化字符串来打印居中的消息,并且使用了脱字符号 ~ 来填充空白。
    6行:如果输入的数值小于2,直接返回 False,因为2是最小的素数。
    8行:对于2到4之间的数,直接返回 True,因为它们都是素数。
    10行:如果 num 是2或3的倍数,则返回 False,因为合数肯定能被2或3整除。
    12行:定义了一个包含小于1000的所有素数的元组 myprimes,这些素数都是大于5的。之所以只需要这些素数,是因为前面的代码已经排除了2和3的倍数。
    13行:通过 iter 函数将 myprimes 转换为一个迭代器。这样做是为了在接下来的循环中逐个使用这些素数。
    15-17行:使用一个 for 循环遍历 myprimes 中的素数。循环中有一个判断,一旦当前素数的平方大于 num,就结束循环。这是因为如果一个数不是素数,那么它必定有一个因子是小于或等于它的平方根的。
    18行:在循环中,如果 num 能够被当前素数整除,那么 num 不是素数,函数返回 False。
    20行:如果循环结束都没有找到能整除 num 的素数,那么 num 是素数,函数返回 True。

      整体来看,这个函数通过排除法来确定一个数是否为素数。它首先排除那些明显不是素数的数(小于2的数和2或3的倍数),然后通过只检查小于1000的素数来减少计算量。这种方法的效率相对较高,尤其是对于较小的数。然而,对于非常大的数,这种方法可能不是最优的,因为它需要预先定义一个相对较大的素数列表。



回页目录


3、结语


  代码没有“最好”只有“更好”,根据实际需求选择适宜的算法和相应的“代码表现形式”,才是“代码编撰”最正确的打开方式。



回页目录


4、我关于“素数”的学习笔记


  • 5个写自定义函数小练习
    地址:https://blog.csdn.net/m0_57158496/article/details/134321362
    浏览阅读:508
    点赞:2 收藏:2 评论:2
    (本篇笔记于2023-11-10 00:37:19首次发布,最后修改于2023-11-10 22:48:13)

  • 幸运素数(找出给定区间的所有幸运素数)
    地址:https://blog.csdn.net/m0_57158496/article/details/134346918
    浏览阅读:341
    点赞:1 收藏:2 
    (本篇笔记于2023-11-11 12:59:47首次发布,最后修改于2023-11-11 22:30:33)

  • 素数查找(def自定义函数练习)
    地址:https://blog.csdn.net/m0_57158496/article/details/118497087
    浏览阅读:332


  • 回页目录


    5、完整源码(Python)

    (源码较长,点此跳过源码)

    #!/sur/bin/nve python 
    # coding: utf-8 
    from time import timedef isPrime(num: int) -> bool:if num > 10**6-1:input(f"\n{' 本函数仅限于查找10^6以内的素数 ':~^28}")return # 退出代码执行返回命令行if num < 2:return False # 剔除2以下的数if 1 < num < 4:return Trueif num%2 == 0 or num%3 == 0:return Falsemyprimes = (5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997) # 1000以内大于5的素数,由于前面已剔除2、3的倍数,就不再试除2、3。本列表仅限于查找100w以内的素数myprimes = iter(myprimes)for i in myprimes:if i*i > num:break if num%i == 0:return Falsereturn True#isPrime(1000_000+1) # 调试报错提示def is_prime(num: int) -> bool:if num < 2:return Falseif num < 4:return Trueif num % 2 == 0 or num % 3 == 0:return False# 使用 for 循环代替 while 循环for i in range(5, int(num**0.5) + 1, 6):if num % i == 0 or num % (i + 2) == 0:return Falsereturn Truedef isPrime4(num: int) -> bool:''' 素数判定 '''if num < 2:return False # 小于2的都不是素数if num == 2 or num == 3:return True # 2和3都是素数elif num%2 == 0 or num%3 == 0:return False # 剔除2、3的倍数for i in range(5, int(num**0.5)+1, 6): # 只检查6k±1的自然数if num%i == 0 or num%(i+2) == 0:  return False # 大于5的素数都满足6k±1的形式,6k形式的数一定是合数return True # 经过前面的排查,就只剩素数了#n = 100
    n: int = 1000_000
    start = time()
    #primes = [i for i in range(n) if is_prime(i)]
    primes = [i for i in range(n) if isPrime(i)]if (k := len(primes))<= 100:print(f"\n{primes}")print(f"\n找到{n}以内的素数有{k}个\n(用时{time()-start:.4f}秒)")



    回页首


    上一篇:  CSDN上的代码块放置(三种方式实现,CSDN文章中代码文本的标准放置,方便阅读者copy,让代码更易于传播)
    下一篇: 



    我的HOT博:

      本次共计收集 311 篇博文笔记信息,总阅读量43.82w。数据于2024年03月22日 00:50:22完成采集,用时6分2.71秒。阅读量不小于6.00k的有 7 7 7篇。

    • 001
      标题:让QQ群昵称色变的神奇代码
      (浏览阅读 5.9w )
      地址:https://blog.csdn.net/m0_57158496/article/details/122566500
      点赞:25 收藏:86 评论:17
      摘要:让QQ昵称色变的神奇代码。
      首发:2022-01-18 19:15:08
      最后编辑:2022-01-20 07:56:47

    • 002
      标题:Python列表(list)反序(降序)的7种实现方式
      (浏览阅读 1.1w )
      地址:https://blog.csdn.net/m0_57158496/article/details/128271700
      点赞:8 收藏:35 评论:8
      摘要:Python列表(list)反序(降序)的实现方式:原址反序,list.reverse()、list.sort();遍历,全数组遍历、1/2数组遍历;新生成列表,resersed()、sorted()、负步长切片[::-1]。
      首发:2022-12-11 23:54:15
      最后编辑:2023-03-20 18:13:55

    • 003
      标题:pandas 数据类型之 DataFrame
      (浏览阅读 9.7k )
      地址:https://blog.csdn.net/m0_57158496/article/details/124525814
      点赞:7 收藏:36 
      摘要:pandas 数据类型之 DataFrame_panda dataframe。
      首发:2022-05-01 13:20:17
      最后编辑:2022-05-08 08:46:13

    • 004
      标题:个人信息提取(字符串)
      (浏览阅读 8.2k )
      地址:https://blog.csdn.net/m0_57158496/article/details/124244618
      点赞:2 收藏:15 
      摘要:个人信息提取(字符串)_个人信息提取python。
      首发:2022-04-18 11:07:12
      最后编辑:2022-04-20 13:17:54

    • 005
      标题:Python字符串居中显示
      (浏览阅读 7.6k )
      地址:https://blog.csdn.net/m0_57158496/article/details/122163023
      评论:1

    • 006
      标题:罗马数字转换器|罗马数字生成器
      (浏览阅读 7.5k )
      地址:https://blog.csdn.net/m0_57158496/article/details/122592047
      摘要:罗马数字转换器|生成器。
      首发:2022-01-19 23:26:42
      最后编辑:2022-01-21 18:37:46

    • 007
      标题:回车符、换行符和回车换行符
      (浏览阅读 6.0k )
      地址:https://blog.csdn.net/m0_57158496/article/details/123109488
      点赞:2 收藏:3 
      摘要:回车符、换行符和回车换行符_命令行回车符。
      首发:2022-02-24 13:10:02
      最后编辑:2022-02-25 20:07:40


    推荐条件 阅读量突破6.00k
    (更多热博,请点击蓝色文字跳转翻阅)

    • 截屏图片
      在这里插入图片描述
        (此文涉及ChatPT,曾被csdn多次下架,前几日又因新发笔记被误杀而落马。躺“未过审”还不如回收站,回收站还不如永久不见。😪值此年底清扫,果断移除。留此截图,以识“曾经”。2023-12-31)



    回页首


    老齐漫画头像

    精品文章:

    • 好文力荐:齐伟书稿 《python 完全自学教程》 Free连载(已完稿并集结成书,还有PDF版本百度网盘永久分享,点击跳转免费🆓下载。)
    • OPP三大特性:封装中的property
    • 通过内置对象理解python'
    • 正则表达式
    • python中“*”的作用
    • Python 完全自学手册
    • 海象运算符
    • Python中的 `!=`与`is not`不同
    • 学习编程的正确方法

    来源:老齐教室


    ◆ Python 入门指南【Python 3.6.3】


    好文力荐:

    • 全栈领域优质创作者——[寒佬](还是国内某高校学生)博文“非技术文—关于英语和如何正确的提问”,“英语”和“会提问”是编程学习的两大利器。
    • 【8大编程语言的适用领域】先别着急选语言学编程,先看它们能干嘛
    • 靠谱程序员的好习惯
    • 大佬帅地的优质好文“函数功能、结束条件、函数等价式”三大要素让您认清递归

    CSDN实用技巧博文:

    • 8个好用到爆的Python实用技巧
    • python忽略警告
    • Python代码编写规范
    • Python的docstring规范(说明文档的规范写法)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/687732.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

打开linux内核的企鹅log

Linux 内核启动的时候可以选择显示小企鹅 logo&#xff0c;只要这个小企鹅 logo 显示没问题那么我 们的 LCD 驱动基本就工作正常了。这个 logo 显示是要配置的&#xff0c;不过 Linux 内核一般都会默认 开启 logo 显示。 打开 Linux内核图形化配置界面&#xff0c;按下路径找到…

【错题集-编程题】最大子矩阵(二维前缀和)

牛客对应题目链接&#xff1a;最大子矩阵_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 ⼆维前缀和矩阵 的应用。 初始化⼆维前缀和矩阵。枚举所有的子矩阵&#xff0c;求出最大子矩阵。 这道题的输入规模最大为 100&#xff0c;用动态规划可以做到 O(n^3)。 下面的做法虽然…

C语言/数据结构——(链表的回文结构)

一.前言 今天在牛客网上刷到了一道链表题——链表的回文结构https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?&#xff0c;巧合的是它的解题思路恰好是我们一起分享过两道链表题的汇总。这两道题分别是反转链表和链表的中间节点。废话不多数&#xff0c…

回炉重造java----单列集合(List,Set)

体系结构: 集合主要分为两种&#xff0c;单列集合collection和双列集合Map&#xff0c;区别在于单列集合一次插入一条数据&#xff0c;而双列的一次插入类似于key-value的形式 单列集合collection 注:红色的表示是接口&#xff0c;蓝色的是实现类 ①操作功能: 增加: add()&am…

Java中的maven的安装和配置

maven的作用 依赖管理 方便快捷的管理项目依赖的资源&#xff0c;避免版本冲突问题 统一项目管理 提供标准&#xff0c;统一的项目结构 项目构建 标准跨平台&#xff08;Linux、windows、MacOS&#xff09;的自动化项目构建方式 maven的安装和配置 在maven官网下载maven Ma…

嵌入式学习<2>:EXTI、ADC、NVIC和AFIO

嵌入式学习_part2 本部分笔记用于学习记录&#xff0c;笔记源头 >>b站江科大_STM32入门教程_EXTI EXTI、ADC、NVIC和AFIO 开发环境&#xff1a;keil MDK、STM32F103C8T6 1 &#xff09;EXTI STM32F10xxx参考手册&#xff08;中文&#xff09;-> 中断与事件 ->…

文本三剑客grep与正则表达式、元字符

正则表达式 正则表达式又称为正规表达式、常规表达式、在代码中常简写为regex、regex或RE。正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串&#xff0c;简单来说&#xff0c;是一种匹配字符串的方法&#xff0c;通过一些特殊符号&#xff0c;实现快速查…

OPC-UA open62541 C++测试代码

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 这是之前写的open62541测试代码…

Mac电脑安装打开APP显示问题已损坏 问题解决

当MAC电脑安装完软件打开时&#xff0c;显示文件已损坏&#xff0c;无法打开。搜了很多教程终于找到解决方案&#xff0c;记录下方便以后再用。 我的mac电脑是intel芯片的&#xff0c;如果你遇到这个问题&#xff0c;可以参考我的这个方案。 1.首先当打开软件后出现 “xx软件已…

【话题】你用过最好用的AI工具有那些

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景一、C知道二、CSDN工具集三、AI工具的普及与受欢迎程度四、AI工具的实际应用与影响五、总结与展望文章推荐 背景 探讨人们在使用AI工具时&#xff0c;最喜欢的和认…

【多客陪玩】陪玩小程序源码APP+小程序+公众号开发 -源码交付,线下可爆改家政,整理师等功能

简述 随着电竞行业的快速发展&#xff0c;电竞陪玩APP正在逐渐成为用户在休闲娱乐时的首选。为了吸引用户和提高用户体验&#xff0c;电竞陪玩APP开发需要定制一些特色功能&#xff0c;并通过合适的盈利模式来获得收益。本文将为您介绍电竞陪玩APP开发需要定制的特色功能以及常…

【漏洞复现】RuvarOA协同办公平台 WorkFlow接口处存在SQL注入

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…