《数学与泛型编程:高效编程的奥秘》一3.2 筛选素数

3.2 筛选素数

毕达哥拉斯学派的人还观察到一个现象,那就是有些数字没有办法表示成非平凡的矩形形状(nontrivial rectangular shape),也就是说,没有办法用两个边都大于1的矩形来表示。这种数叫做素数(prime number),它们不能够用比其更小且大于1的数之间的乘积来表示:
2, 3, 5, 7, 11, 13,…
(古希腊人所说的数都是指整数。)某些与素数有关的特征最早是由欧几里得观察到的。尽管大家通常都会把他与几何学联系起来,但是《几何原本》中有很多卷内容其实是在讲数论。他所得到的其中一项结论就是下面这条定理:
定理3.1(《几何原本》第7卷第32号命题) 任何数要么是素数,要么可以为某个素数所整除。
该定理的证明过程采用了一项技巧,它通过无穷递降法(infinite descent)推导出一种不可能存在的情形。我们可以将此过程陈述如下:
证明 考虑A这个数。如果它是素数,那么就得证。如果它是合数(composite,也就是非素数(nonprime)),那么必定能够为某个更小的数B所整除。如果B是素数,那么得证(由于A可以为B所整除,而B又是素数,因此A就可以为该素数所整除)。如果B是合数,那么必定能够为某个更小的数C所整除,依此类推,我们最后必然能够找到一个可以整除A的素数,假如找不到这样的素数,那么就会像欧几里得在证明同卷第31号命题时所说的那样:得到一个无穷数列(infinite sequence of numbers),其中的每个数都可以整除A,而且后一个数要比前一个数小。然而这样一种数列是不可能存在的。□
欧几里得的证明过程依赖于一项原则,那就是:由降序的自然数所形成的数列必定会终结。此原则与我们将要在第9章提到的自然数归纳公理(induction axiom of natural numbers)是等价的。

    • *
      欧氏所得出的另一条结论,是说素数的个数无限多,有人认为这是最美的数学定理:

定理3.2(《几何原本》第9卷第20号命题) 对于由素数所构成的任何一个数列{p1,…, pn}来说,总有一个素数p不在该数列中。
证明 考虑下面这个数:

其中的pi是指数列中的第i个素数。根据q的构造方式可知,它不可能为任何一个pi所整除。因此,q要么本身就是素数,要么则可以为不在数列中的其他某个素数所整除。如果是前一种情况,那么q必然不在这个数列中;如果是后一种情况,那么根据该数列的定义可知,能够整除q的那个素数也不在这个数列中。因此,素数的个数是无限多的。
有一种广为人知的素数搜寻方法,叫做埃拉托斯特尼筛法(Sieve of Eratosthenes)。埃拉托斯特尼是公元3世纪的希腊数学家,他的一项壮举是相当精确地测量了地球的周长。这种素数搜寻算法的原理是将数字放在筛子里进行筛选,把其中的非素数筛掉,使得素数能够留在筛子里面。执行算法时,要把所有的候选数字写下来,然后将其中已知的非素数划掉(这些数都是已经找到的那些素数的倍数),剩下来的数就是素数。今天在演示该算法的时候,会把从2到某个给定值之间的所有数字全部写下来,但由于埃拉托斯特尼当时已经知道2之外的偶数都不是素数,因此他并没有把这些数包含在内。
下面我们也按照埃氏的习惯,将偶数排除在外,也就是说,只寻找大于2的那些素数。我们把从3开始直到给定值(该值记为m)之间的每一个候选数字,都放在筛子里面。比方说,如果要寻找3到53(此时m = 53)之间的素数,那么筛子里面一开始会有这些数字:

反复执行这个筛选过程,直到把小于等于的倍数全都划掉为止,其中的m是指候选数字里面最大的那个数。
对于本例来说,由于m = 53,因此只需要执行到7的倍数这一轮就可以停止了。还没有划掉的数字全都是素数:

在用程序代码实现该算法之前,我们先来观察它的几项特征。在筛选过程进行到一半的时候(比方说,在正要划掉5的倍数时),我们给候选数字添加一些信息,也就是把每个数字在数列中的序号(index)或者说位置标在该数上方。

大家可以看到,在考虑5的倍数时,我们所划掉的25和35这两个数字,其距离恰好是5,这个间隔距离就叫做步长(step size)。如果改用另外一种说法,那就是:在某一轮筛选过程中所划掉的这两个候选数字,其序号之间的差距等于本轮开头所用的那个素数。此外,由于候选数列中只包含奇数,因此,划掉的这两个数值其数量差距是序号差距的2倍。所以我们可以说,某一轮筛选过程中所划掉的这两个候选数字(例如25和35)其数量差距是步长的2倍,或者说是本轮开头所用的那个素数的2倍。刚才我们是以5为例来进行说明的,对于其他数字来说,这个规律同样成立。
最后,我们还观察到另外一个现象,那就是:每一轮筛选时,第一个划掉的数字总是当前这一轮所用的那个素数的平方。例如在考虑5的倍数时,第一个划掉的数字必然是25,因为尽管两者之间还有一些数字也是5的倍数,但我们早前在考虑其他素数时,已经把那些数划掉了。

时间: 2024-09-19 12:06:42

《数学与泛型编程:高效编程的奥秘》一3.2 筛选素数的相关文章

《数学与泛型编程:高效编程的奥秘》一导读

前言 如果将计算机科学与数学分离,那么这两者的发展都会有很大困难.于是,我们就试图通过一些课程,把人类文明早期就有的数学活动与现代才有的计算机活动结合起来.本书正是基于这样一种课程而编写的.能够与友人Dan Rose合作,我深感荣幸.他的管理工作令我们团队能够把泛型编程的原则运用到搜索引擎的设计上来,而且他愿意把我原来那些相当分散的课程内容集结成现在这样一本连贯的书籍.Dan和我都希望读者能够喜欢我们这次合作的成果.--A.A.S. 大家将要阅读的这本书是根据"Algorithmic Journ

《数学与泛型编程:高效编程的奥秘》一1.1 编程与数学

1.1 编程与数学 那么,这种泛型编程的想法是从哪里来的?我们又应该怎样来学习它呢?这种想法是从数学中衍生出来的,尤其与抽象代数(abstract algebra)这个数学分支有关.为了使大家能够理解这种编程方式,本书会对抽象代数做一些介绍,并着重讲解怎样从抽象的运算属性来认识对象.这个话题一般是数学专业的大学生才去研究的,然而笔者认为,它对于我们理解泛型编程会起到关键的作用.实际上,还有很多基本的编程概念也同样来自数学.对这些概念的产生及变化过程加以学习,能够促使我们更好地思考软件的设计问题.

《数学与泛型编程:高效编程的奥秘》一第1章 内容提要

第1章 内 容 提 要 不懂数学,就无法了解世界. --罗吉尔·培根(Roger Bacon),<大著作>(Opus Majus) 这是一本谈编程的书,但是它与大多数的编程书都不太一样,因为除了算法和代码之外,本书还会给出数学证明和一些讲述从古代到20世纪各种数学发现的历史材料. 另一个更为具体的特色在于:这是一本谈论泛型编程(generic programming)的书.泛型编程是出现于20世纪80年代的编程方法,在20世纪90年代随着C++标准模板库(Standard Template L

《数学与泛型编程:高效编程的奥秘》一2.2 改进该算法

2.2 改进该算法 从加法的执行次数上面来看,multiply1函数确实做得不错,但它毕竟执行了?log n?次递归调用.由于函数调用的开销很大,因此我们想把程序中的递归调用去掉,以避免此类开销. 在对函数进行转化时,我们所秉持的一项理念是:通用的工作实现起来经常比具体的工作还要简单(It is often easier to do more work rather than less.).就本例来说,我们要按照下面这种通用的方式进行计算: r + na 其中的r是一个会在运算过程中持续更新的值

《数学与泛型编程:高效编程的奥秘》一1.3 阅读准备

1.3 阅读准备 由于书中的很多内容都和数学有关,因此你可能担心自己必须先具备丰富的数学知识,然后才能看懂这本书.其实你只要有逻辑思考能力就行(程序员应该很擅长逻辑思考),笔者并不会要求大家具备中学代数与中学几何之外的其他数学知识.某些章节可能会运用向量(vector)与矩阵(matrix)等线性代数(linear algebra)方面的概念,如果从前没有看过这方面的资料,那么把这些内容跳过去就可以了.若是对本书所用的记法不够熟悉,则请参考附录A. 数学中有一个很重要的部分就是对命题给出形式化证

《数学与泛型编程:高效编程的奥秘》一第2章 算法初谈

第2章 算 法 初 谈 摩西很快就学会了算术与几何. --这些知识是他从埃及人那里学来的, 埃及人最重视的研究科目是数学. --亚历山大的斐洛(Philo of Alexandria),<摩西生平>(Life of Moses) 算法(algorithm)是用来完成计算任务的一系列有限步骤.由于算法与计算机编程的关系特别密切,因此很多人或许认为,算法是一个来自计算机科学专业的概念.其实算法这个词已经有几千年历史了.数学中充满了各种各样的算法,有些算法我们天天在用,就连小学生计算加法时所用的竖式

《数学与泛型编程:高效编程的奥秘》一3.1 整数的几何属性

3.1 整数的几何属性 毕达哥拉斯(Pythagoras)这个名字,大多数人都是从同名的定理中听说的.这位古希腊的数学家和哲学家曾经提出一个理念:要想理解世界,就必须先懂得数学.他还发现了数字的很多奇妙性质,而且认为这些发现无论有没有实际的用途,其本身都具备巨大的价值.亚里士多德的学生亚里士多塞诺斯(Aristoxenus)曾经说道:"他极其重视算术研究工作,并把这些研究从实用的商业领域中划分出来,单独加以推进." 毕达哥拉斯(Pythagoras,约公元前570-公元前490) 毕达

《数学与泛型编程:高效编程的奥秘》一1.2 从历史的角度来讲解

1.2 从历史的角度来讲解 如果能把某个话题融入故事中,那么我们学起来就会更容易一些,而且也会觉得更为有趣.我们想要知道:在某个时间发生了什么事件?都有谁与该事件相关?这些人是怎样产生某种想法的?他们是要在别人的基础之上进行研究,还是要驳斥别人的结论?为此,本书在介绍数学概念时,还会讲一些与此有关的故事,并谈一下提出这些概念的人.笔者通常用一份简要的传记来描述身为故事主角的数学家,这些小传不会像百科全书里面写得那样详尽,它只是想令你对这位数学家的情况有所了解而已. 尽管我们会从历史的角度来谈论某

《数学与泛型编程:高效编程的奥秘》一3.7 本章要点

3.7 本章要点 古希腊人对数字的"形状"以及其他一些属性(例如是不是素数,是不是完美数等)很着迷,这就给数论这一数学领域打下了基础.他们所提出的某些算法(例如埃拉托斯特尼筛法)即便在今天来看,也是相当优雅的,只不过我们还可以通过某些现代的优化技术来继续提升其效率. * 读完本章之后,大家已经看到了两种能够证明是无理数的方法,一种是几何方法,另一种是代数方法.能够针对同一个数学现象提出两种完全不同的证明,这是相当好的结果,而且数学家实际上也必须像这样去寻找同一个数学现象的多种证法,以增