质数的费马检查

质数的费马检查

SICP 1.2.6 介绍了一种对数复杂度的素数检查方法。

问题背景

质数又称素数。对于大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫质数;否则称合数。1既不是质数也不是合数。

如何编程检查一个数是不是质数?我所知道的方法有:

  • 因数排查
  • 素数筛
  • 费马检查

其中,费马检查是一种概率算法,有一定的错误率。

数学原理与编程实现

费马小定理

  • 如果 n n n是质数, a a a是小于 n n n的任意正整数,那么 a n − 1 ≡ 1 ( m o d   n ) a^{n-1}\equiv 1(mod\ n) an11(mod n).

费马小定理描述了质数的一个性质,满足此性质的却不都是质数。

此定理指导我们编程如下,

def fermat_test(n):
    import random
    a = random.randint(1, n - 1)
    return a**(n - 1) % n == 1

然而,Carmichael数很可能骗过费马检查。Carmichael数不是质数,但是很可能通过费马检查。

使用下列实验代码:

Carmichaels = 561, 1105, 1729, 2465, 2821, 6601
normal_numbers = 563, 1107, 1727, 3465, 4821, 6607
ns = Carmichaels
for n in ns:
    t = [i**(n - 1) % n == 1 for i in range(1, n)]
    print('%-5d%8.2f' % (n, sum(t) / len(t)))

上面这段代码计算Carmichael数通过费马检查的概率,结果如下:

Carmichael通过费马检查的概率
5610.57
11050.70
17290.75
24650.73
28210.77
66010.80

通过率都高于50%!与此相对,一般合数的费马通过率都接近于0.

二次探测定理

  • 如果 n n n是质数,则 x 2 ≡ 1 ( m o d   n ) x^2\equiv1(mod\ n) x21(mod n)的解为 x = 1 x=1 x=1 x = n − 1 x=n-1 x=n1.

只要在检验 a n − 1 ≡ 1 ( m o d   n ) a^{n-1}\equiv 1(mod\ n) an11(mod n),即计算 a n − 1 m o d   n a^{n-1}mod\ n an1mod n时,检查中间平方步骤的得数。如果遇到“ 1 1 1取模 n n n的非平凡平方根”,即 1 1 1 n − 1 n-1 n1之外的 x x x满足 x 2 ≡ 1 ( m o d   n ) x^2\equiv1(mod\ n) x21(mod n),那么 n n n就不是质数。

def miller_rabin_test(n):
    def non_trival_sqrt(n, m):
        if n == 1 or n == m - 1:
            return False
        return n**2 % m == 1
    
    def expmod(base, exp, m):
        if exp == 0:
            return 1
        elif exp % 2 == 0:
            x = expmod(base, exp // 2, m)
            if non_trival_sqrt(x, m):
                return 0
            else:
                return x**2 % m
        else:
            return base * expmod(base, exp - 1, m) % m
    a = random.randint(1, n - 1)
    return expmod(a, n - 1, n) == 1

这就是Miller-Rabin检查。经实验,Miller-Rabin检查能大大降低Carmichael数的通过率。

CarmichaelMiller-Rabin通过率
5610.02
11050.03
17290.09
24650.03
28210.10
66010.05

参考资料

  1. SICP
  2. 非递归实现
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值