热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SICP:费马小定理与素数检测

我知道费马等一些人都热衷于“纯数学”,那些被看起来毫无实用价值的“纯理论”,可这费马检查,却是全世界的服务器每秒中都要运行无数次的RSA算法的理论基石。就我自己而言,每天使用SSH的时候都要用到。而几位科学家把这这一切联系起来的过程,实在称得上是“玄妙”了。

SICP 1.2.6

费马小定理

关于费马小定理,读到注解的时候,还是有点震撼的。

皮埃尔?得?费马(1601-1665)是现代数论的奠基人,他得出了许多有关数论的重要理论结果,但他通常只是通告这些结果,而没有提供证明。费马小定理是在1640年他所写的一封信里提到的,公开发表的第一个证明由欧拉在1736年给出(更早一些,同样的证明也出现在莱布尼茨的未发表的手稿中)费马的最著名结果——称为费马的最后定理——是l637年草草写在他所读的书籍《算术》里(3世纪希腊数学家丢番图所著),还带有一句注释“我已经发现了一个极其美妙的证明,但这本书的边栏太小,无法将它写在这里”。 找出费马最后定理的证明成为数论中最著名的挑战。完整的解最终由普林斯顿大学的安德鲁?怀尔斯在1995年给出。

我知道费马等一些人都热衷于“纯数学”,那些被看起来毫无实用价值的“纯理论”,可这费马检查,却是全世界的服务器每秒中都要运行无数次的 RSA 算法的理论基石。就我自己而言,每天使用 SSH 的时候都要用到。而几位科学家把这这一切联系起来的过程,实在称得上是“玄妙”了。

费马小定理:

如果 n 是一个素数,a 是小于 n 的任意正整数,那么 a 的 n 次方与 a 模 n 同余。(两个数称为是模 n 的同余,如果它们除以 n 的余数相同。数 a 除以 n 的余数称为 a 取模 n 的余数,或简称为 a 取模 n)。

如果 n 不是素数,那么,一般而言,大部分的 a

对于给定的整数 n,随机任取一个 a

读起来理解不直观?那么我这么总结下吧。

假如a是一个整数,p是一个素数,那么 ap = a (mod p)

如果a不是p的倍数,这个定理也可以写成 ap-1 = 1 (mod p)

举个例子,67是一个素数,则266 mod 67 = 1。

费马检测

费马检测基于费马小定理,费马小定理:

如果n是一个素数,a是小于n的任意正整数,那么a的n次方与a模n同余。

但是如果n不是素数,一般来说大部分的 a

实现费马检查的的方法:

;; 计算一个数的幂对另外一个数取模的结果
;; 
(define (expmod base exp m)
        ;; 如果 exp 等于 0,那么返回0
  (cond ((= exp 0) 1)
        ;; 如果 exp 是偶数
        ((even? exp)
         ;; square(expmod(base (exp/2) m)) % m
         (remainder (square (expmod base (/ exp 2) m))
                    m))
        ;; 如果不是偶数
        (else
         ;; (base * expmod(base(ex1 - 1) m)) % m
         (remainder (* base (expmod base (- exp 1) m))
                    m))))

;; 费马检测
(define (fermat-test n)
  ;; 定义方法调用expmod
  (define (try-it a)
    (= (expmod a n n) a))
  (try-it (+ 1 (random (- n 1)))))

;; 快速求素数
(define (fast-prime? n times)
  (cond ((= times 0) true)
        ((fermat-test n) (fast-prime? n (- times 1)))
        (else false)))

expmod 函数实现了求 base 的 exp次幂,然后再将结果余上m,得出来的结果再与a比较,如果相等,那么这个数可能为素数。

费马检测的C语言实现

由于 lisp 的语法太过奇葩,在这里贴一个 C/C++ 的实现吧:

#include "stdio.h"
#include "math.h"

#define TRUE 1
#define FALSE 0

typedef int Status;

int square(int n)
{
    return n*n;
}
/*---------------------------------------------------
计算一个数的幂对另一个数取模的结果,
确定是否素数所需的步数将具有θ(log n)的增长阶
---------------------------------------------------*/
int expmod(int base, int exp, int m)
{
    if (exp == 0)
    {
        return 1;
    }
    else if ((exp % 2) == 0)
    {
        return square(expmod(base, exp / 2, m)) % m;
    }
    else
    {
        return (base * (expmod(base, exp - 1, m))) % m;
    }
}

/*---------------------------------------------------
执行费马检查需要选取位于1和n-1之间(包含这两者)的数a,而后检查a的n次幂取模n的余数是否等于a.
---------------------------------------------------*/
Status fermat_test(int n)
{
    int a = rand() % n; /*a random int, less than n*/
    printf("本次随机值为%d\n", a);
    if( a == expmod(a, n, n) )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
/*
bool fermat_test(int n)
{
    // a is a random number in range (1~99)
    int a = rand() % (n - 1) + 1;
    return expmod(a, n, n) == a;
}
*/

Status fermat_prime(int n, int times)
{
    if (0 == times)
    {
        return TRUE;
    }
    else if( fermat_test(n) )
    {
        return fermat_prime(n, times-1);
    }
    else
    {
        return FALSE;
    }
}

Status is_prime(int n, int test_count)
{
    int i;
    // The result can be extremely reliable
    // when TEST_COUNT is big enough.
    for (i = 0; i 

费马检测是一个相对可靠的算法,而且在实现大数判断素数时可以提供相对高的效率来工作。下面看看费马检测概率问题。

概率方法

从特征上看,费马检查与我们前面已熟悉的算法都不一样。前面那些算法都保证计算的结果一定正确,而费马检查得到的结果则只有概率上的正确性。说得更准确些,如果数 n 不能通过费马检查,我们可以确信它一定不是素数。而 n 通过了这一检查的事实只能作为它是素数的一个很强的证据,但却不是对 n 为素数的保证。我们能说的是,对于任何数 n,如果执行这一检查的次数足够多,而且看到 n 通过了检查,那么就能使这一素数检查出错的概率减小到所需要的任意程度。

不幸的是,这一断言并不完全正确。因为确实存在着一些能骗过费马检查的整数:某些数 n 不是素数但却具有这样的性质,对任意整数 a

能够证明,存在着使这样的出错机会达到任意小的检查算法,激发了人们对这类算法的极大兴趣,已经形成了人所共知称为概率算法的领域。在这一领域中已经有了大量研究工作,概率算法也已被成功应用于许多重要领域。

PS 1:能够骗过费马检查的数称为 Carmichael 数,我们对它们知之甚少,只知其非常罕见,在 100 000 000 之内有 255 个 Carmichael 数,其中最小的几个是 561、1105、1729、2465、2821 和 6601。在检查很大的数是否为素数时,所用选择是随机的。撞上能欺骗费马检查的值的机会比宇宙射线导致计算机在执行“正确”算法中出错的机会还要小。对算法只考虑第一因素而不考虑第二因素恰好表现出数学与工程的不同。

PS 2:概率素数检查的最惊人应用之一是在密码学的领域中。虽然完成 200 位数的因数分解现在在计算机上还是不现实的,但用费马检查却可以在几秒内判断这么大的数的素性。这一事实成为 Rivset、Shamir 和 Adleman (1977) 提出的一种构造“不可摧毁的密码”的技术基础,这一 RSA 算法已经成为提高电子通信安全性的一种使用广泛的技术。因为这项研究和其他相关研究的发展,素数研究这一曾被认为是“纯粹”数学的缩影,是仅仅因为其自身原因而被研究的课题,现在已经变成在密码学、电子资金流通和信息查询领域里有重要实际应用的问题了。

后话

本来想一篇文章搞定素数检测与费马小定理,但是发现这个素数检测是个大坑,里面还有很多东西挖据。既然开坑了,后面开个专题慢慢填坑吧。。。不断开坑,不断填坑,学到的东西会很多。

本文地址:http://www.nowamagic.net/librarys/veda/detail/2329,欢迎访问原出处。


推荐阅读
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • 掌握远程执行Linux脚本和命令的技巧
    本文将详细介绍如何利用Python的Paramiko库实现远程执行Linux脚本和命令,帮助读者快速掌握这一实用技能。通过具体的示例和详尽的解释,让初学者也能轻松上手。 ... [详细]
  • 深入解析 Spring Security 用户认证机制
    本文将详细介绍 Spring Security 中用户登录认证的核心流程,重点分析 AbstractAuthenticationProcessingFilter 和 AuthenticationManager 的工作原理。通过理解这些组件的实现,读者可以更好地掌握 Spring Security 的认证机制。 ... [详细]
  • 本文将深入探讨PHP编程语言的基本概念,并解释PHP概念股的含义。通过详细解析,帮助读者理解PHP在Web开发和股票市场中的重要性。 ... [详细]
  • 本文介绍如何在现有网络中部署基于Linux系统的透明防火墙(网桥模式),以实现灵活的时间段控制、流量限制等功能。通过详细的步骤和配置说明,确保内部网络的安全性和稳定性。 ... [详细]
  • 优化局域网SSH连接延迟问题的解决方案
    本文介绍了解决局域网内SSH连接到服务器时出现长时间等待问题的方法。通过调整配置和优化网络设置,可以显著缩短SSH连接的时间。 ... [详细]
  • Git管理工具SourceTree安装与使用指南
    本文详细介绍了Git管理工具SourceTree的安装、配置及团队协作方案,旨在帮助开发者更高效地进行版本控制和项目管理。 ... [详细]
  • 本文探讨了如何使用自增和自减运算符遍历二维数组中的元素。通过实例详细解释了指针与二维数组结合使用的正确方法,并解答了常见的错误用法。 ... [详细]
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • Python 工具推荐 | PyHubWeekly 第二十一期:提升命令行体验的五大工具
    本期 PyHubWeekly 为大家精选了 GitHub 上五个优秀的 Python 工具,涵盖金融数据可视化、终端美化、国际化支持、图像增强和远程 Shell 环境配置。欢迎关注并参与项目。 ... [详细]
  • 本文详细介绍了如何检查和配置电脑上的PHP环境,包括位数、运行支持以及文件格式的打开方式。适合初学者了解PHP的基础知识和操作方法。 ... [详细]
  • 本文介绍了一种基于选择排序思想的高效排序方法——堆排序。通过使用堆数据结构,堆排序能够在每次查找最大元素时显著提高效率。文章详细描述了堆排序的工作原理,并提供了完整的C语言代码实现。 ... [详细]
  • 云屏系统基于嵌入式微系统msOS,旨在解决当前嵌入式彩屏GUI编程中硬件要求高、软件开发复杂、界面效果不佳等问题。该系统通过结合MCU和Android技术,利用Html5+JavaScript实现高效、易用的图形用户界面开发,使嵌入式开发人员能够专注于业务逻辑。 ... [详细]
  • 本文介绍如何配置SecureCRT以正确显示Linux终端的颜色,并解决中文显示问题。通过简单的步骤设置,可以显著提升使用体验。 ... [详细]
author-avatar
NOYOKI要跑偏
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有