质数判断居然这么复杂?一篇文章带你搞透质数判断那些事

大家好,我是干货哥!今天我们继续深入探讨质数判断的那些事儿。你可能以为质数判断无非就是用除法轮番上阵,其实没错,但如果我告诉你,可以通过一些运算让这些常见的方法速度翻倍,甚至百倍,你信不信?今天,我就带你揭秘如何用运算优化,让质数判断变得飞一般的快!

1. 基本方法:试除法

你可能最先想到的质数判断方法就是试除法。它的思路简单明了:要判断一个数 ( n ) 是否是质数,只要尝试用比它小的数去除它,如果找不到可以整除它的数,那 ( n ) 就是质数。乍一看,这方法没啥毛病,但效率实在不敢恭维。要是碰上个大数,你可能得挨个儿除上几十万次。

最基本的:位运算优化

  1. 偶数优化:判断一个数是否是偶数,我们通常会用 n % 2 == 0。但你可能不知道,位运算更快!只需 n & 1 == 0,轻轻一操作,速度直接上来了。

  2. 跳过明显非质数:你知道所有能被 2 或 3 整除的数都不是质数,那还需要傻傻地继续计算吗?不!我们用位运算快速跳过。

def is_prime_basic(n):
    if n <= 1:
        return False  # 1 和更小的数都不是质数
    if n <= 3:
        return True  # 2 和 3 是质数
    if (n & 1) == 0 or n % 3 == 0:
        return False  # 偶数或能被3整除的数都不是质数

    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False  # 如果 n 能被 i 或 i+2 整除,则 n 不是质数
        i += 6

    return True

你以为这就结束了?我们来点更高级的!

2. “6k ± 1”优化

你可能以为试除法就这么简单?NO,NO,NO!试除法还可以进一步优化。除了直接跳过偶数和3的倍数外,我们可以利用一个更高级的技巧:6k ± 1。别看这个公式简单,它的实际作用却非常强大!

什么是“6k ± 1”?其实就是6的倍数减去1和加上1的位置,比如 5 和 7,11 和 13,17 和 19 等等。因为质数除了2和3,其他质数都可以写成 6k ± 1 的形式。利用这一点,我们可以把试除法的次数再减少一半!

def is_prime_6k_1(n):
    if n <= 1:
        return False
    if n <= 3:
        return True
    if (n & 1) == 0 or n % 3 == 0:
        return False

    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i += 6

    return True

通过这种优化,试除法的效率直接飙升!再也不用担心慢得要死的情况了。

你以为这就是巅峰了?复杂算法才刚刚登场!

上面这些优化是不是已经让你感到惊喜?不过,这只是个开胃菜!接下来,干货哥带你进入质数判断的高级阶段,让你见识一下真正的质数判断法——那些用上位运算、概率算法、甚至筛法来进行质数判断的“重武器”。

蒙特卡罗算法:质数判断中的蒙面高手!

你可能会想,判断一个数是不是质数,直接从2开始除,能整除的就不是质数,不能整除的就是质数,这不是理所当然吗?但是,真的是这样吗?很多人都这么做,但真的对吗?蒙特卡罗算法要对你说“NO”!

蒙特卡罗算法可是质数判断中的蒙面高手,它不仅速度飞快,还能让你在没搞清楚的情况下,赌一个结果——是的,你没听错,它是基于概率的!你以为概率算法就是不靠谱?那你就错了!蒙特卡罗算法就是这么狂,利用费马小定理,以一种近乎魔法的方式来验证一个数是否为质数。只要你选择的“随机种子”足够神秘,它的准确性就会让你大吃一惊!但你也要小心,虽然它大多数时候是对的,但偶尔它也会出错,这正是它神秘和有趣的地方!

import random

# 计算 base^exp % mod 的快速幂方法
def power_mod(base, exp, mod):
    result = 1  # 初始化结果
    base = base % mod  # 处理 base 可能大于 mod 的情况
    
    while exp > 0:
        # 如果当前指数是奇数,乘上当前的 base
        if exp & 1:  # 等价于 exp % 2 == 1
            result = (result * base) % mod
        
        exp >>= 1  # 指数除以2(使用位运算右移一位)
        base = (base * base) % mod  # base 自乘,并取模
    
    return result

# 蒙特卡罗算法判断质数
def is_prime_monte_carlo(n, k=5):
    if n <= 1:
        return False  # 1 和更小的数都不是质数
    if n <= 3:
        return True  # 2 和 3 是质数
    if (n & 1) == 0 or n % 3 == 0:
        return False  # 排除 2 和 3 以外的偶数以及被3整除的数
    
    for _ in range(k):
        # 随机选择一个 a,范围是 [2, n-2]
        a = random.randint(2, n - 2)
        
        # 使用快速幂计算 a^(n-1) % n,如果结果不等于1,n一定不是质数
        if power_mod(a, n - 1, n) != 1:
            return False
    
    # 经过 k 次测试后仍然没有被判定为合数,那么有较高概率是质数
    return True

埃拉托色尼筛法:质数判断的终极武器!

质数判断还有一位重量级选手——埃拉托色尼筛法!你以为质数判断只是逐个排查?那你对这位选手完全低估了!埃拉托色尼筛法不是慢吞吞地排查每一个数,而是像一个战术高手,直接用大扫除的方式剔除所有的非质数,简直是质数世界的“终极武器”!

埃拉托色尼筛法的威力在于它的效率,只要你设定了一个范围,它就能飞速地筛出所有的质数。而这个过程简直就像“扫雷”一样:从2开始,把所有2的倍数都标记为非质数,然后是3,再把3的倍数都干掉,依次进行,直到你筛完所有可能的质数。最后剩下的那些,才是真正的精英!是不是很酷?

# 埃拉托色尼筛法实现的质数判断
def sieve_is_prime(n):
    if n <= 1:
        return False  # 1 和更小的数都不是质数
    
    # 创建一个布尔列表,初始化为 True,表示所有数字都是潜在的质数
    sieve = [True] * (n + 1)
    sieve[0] = sieve[1] = False  # 0 和 1 不是质数
    
    # 遍历所有小于等于 sqrt(n) 的数
    for i in range(2, int(n**0.5) + 1):
        if sieve[i]:  # 如果 i 是质数
            # 将 i 的所有倍数标记为合数
            for j in range(i * i, n + 1, i):
                sieve[j] = False
    
    # 返回 n 是否是质数
    return sieve[n]

这就是今天的内容,喜欢的话记得点赞、收藏和分享!我是干货哥,我们下次再见!

怎么样,干货是不是足够硬核?从基础的试除法,到“6k ± 1”优化,再到蒙特卡罗算法和埃拉托色尼筛法,质数判断的世界比你想象的还要丰富和复杂。而且,只要用上位运算,你的算法就能像火箭一样飞速提升!

还想了解更多的编程干货?别忘了关注干货哥,下次我们继续为你带来更多惊喜!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值