素数并不孤独( 三 )


关于布伦常数,还有个有趣的小插曲 。1994年,美国一位教授在计算布伦常数时,无意中发现当时英特尔公司的奔腾处理器在计算浮点除法时,在极稀有的情况下,会产生错误的结果 。虽然英特尔声明这种错误对于日常使用来说不足为患,但对于消费者来说,这种托辞实在难以接受 。最后,英特尔不得不承诺免费更换有问题的处理器 。帮助发现硬件问题,这可算是数论在现实中的一个小小应用 。
但布伦的证明意义远不止于此 。他的这个证明,正是现代筛法的开端 。
布伦所用的筛法,根源可以追溯到古希腊的埃拉托色尼筛法 。还记得我们怎么用埃拉托色尼筛法列出素数表吗?每次获得一个新的素数,我们都要划去所有新素数的倍数,然后剩下最小的数又是一个新的素数 。用类似的方法,我们可以估计在某个区间中,比如说在N 和2N 之间,大约有多少素数 。
首先,我们假设手头上已有足够大的素数表(大概到2N ? ? ? √ 的所有素数) 。用这个素数表,我们打算把从N 到2N 的所有合数都划去一遍,剩下的就是素数 。对于每个素数p ,我们将所有p 的倍数划去一遍 。在N 和2N 之间,对于每个素数p ,大约有N/p 个这样的倍数 。当然,如果N 不是p 的倍数,这样的估计会有误差,但在数学家看来,只要能把握误差的大小,最终仍然可以得到正确的结论 。
这样,剩下的数的个数就是N 减去所有N/p 的和,是这样吗?并不尽然,因为有些数可能被划去了几次 。比如说1000,它能被2整除,也能被5整除,于是在处理2和5的倍数时,它分别被划去了两遍 。对于每一对素数p 1 ,p 2 ,每个p 1 p 2 的倍数在之前都被划去了两遍,而我们只希望将它们划去一遍 。为了得到正确结果,我们需要对这些数作出补偿:将这些数加回去,一共是N/p 1 p 2 个,加上一点点误差 。
但这就是尽头吗?如果考虑三个素数的倍数,我们发现补偿得又太多了,需要重新划去;继续考虑四个素数的倍数,划去得又太多了,需要重新补偿……如此一正一反,损有余,补不足,一项一项估计下去,才能从自然数的海洋中,精确筛选出所有我们想要计算的那些素数 。
但我们是否需要做到如此精细呢?在整个计算中,虽然每一项看似简单,但简单的代价是误差 。虽然每一项的误差很小,但因为数目巨大,累土而成九层之台,累计误差可以比需要估计的量还要多 。所以,在现代的筛法中,过于精细反而是一种累赘 。况且,我们的目的是获得上界或者下界,所以结果无需完美,只需误差可控 。一般而言,由于越到后面的项贡献越小,往往忽略它们的计算,直接将其计入误差 。这样可以有效减少需要计算的项的数目,同时也能间接减少误差 。当然,如果忽略的项太多,它们引起的误差又会太大,也会导致不够精确的结果 。
布伦相对于前人的改进,正在于此 。如果盲目计算所有的项,必然深陷误差的泥沼 。而布伦则大胆截去那些贡献很小却占绝大多数的项,而对于剩下的项也果断采用更粗放的近似来简化计算 。虽然看似不依章法,但通过仔细调校,布伦得以有效控制总误差,从而获得他想要的结果 。
布伦的这个思路,开启了解析数论之中一大类方法的大门 。我们不知道怎么数素数,是因为它们的分布实在难以捉摸 。而现在,布伦的筛法指出了一条用简单的集合来逼近素数集合的道路,这自然令数学家如获至宝 。
在更精细的筛选与更微小的误差之中寻找那一线的平衡,这大概是筛法的醍醐 。但这样的平衡,显然依赖于我们如何估计每一项的具体数值 。可以每项分开估计,但合起来也无伤大雅 。无论做法如何,估计的误差越小,筛选可以越深入,结果也越逼近真实 。即使估计方法不变,如果有更好的方法决定每一项的取舍,取贡献大而误差小之项,而舍贡献小而误差大之项,当然也能得到更好的结果 。
但为何拘泥于每一项?对于每一项,为什么要么取要么不取,不能站在中间立场吗?只要能控制误差,将每一项拆解开来,根据贡献和误差来赋予不同的权值,再求和,这样的结果岂不是更精细?再者,有时不拘泥于素数,放松限制去筛选那些“殆素数”,也就是那些只有少数几个素因子的数,在某些情况下也能得到更好的结果 。在严谨的前提下,只要能做出更好的结果,数学家对于突破原有思路毫不犹豫 。
这就像一场对素数的围捕战 。数学家们拿着筛法这个工具,不断打磨它、改装它,不断练习,正着用,反着用,与别的领域的工具配合着用,绞尽脑汁发明新的用法,殚精竭力用它来围捕那些调皮的素数 。欲擒故纵,反客为主,无中生有,李代桃僵,数学家们在对各种各样素数的围捕中,借着筛法,将一套兵法使得淋漓尽致,精彩之处,三国亦为之失色 。