这个题目是现代软件工程老师布置的一个个人项目,当看到这个题目第一个想到的就是筛法。然而仔细考虑下,筛法的信息冗余量实在太大,我要求第N个素数,却把前N个素数都求了出来,那有没有一个直接能求解第N个素数是什么的方法呢?答案当然是。。。没有。但是,有一种方法用迭代的方法能够求解π(x),即是0~x中素数的个数,它就是梅塞尔—勒梅尔公式,黑科技一般的公式。具体这个公式是什么样的,贴出来太麻烦,可以去wiki看一下,搜索素数计数函数即可(中文版需FQ)。
把这个问题搞定后,怎么求得第N个素数呢?显然当N小于梅塞尔—勒梅尔准备素数的个数时,直接从数组调取即可。当N很大时,我们可以用近似比例微分(PD)的调节方式来使π(x)快速逼近N,这里D项的系数可以参照素数在不同数量级大致的分布密度,P项系数可以默认为1。然而问题还没有解决,一方面是PD调节在系数不是很完美的情况下会出现在目标值附近震荡的情况,另一方面就是即恰好π(x)为N,也不能确定x就是第N个素数。对于第一个方面,由于D项的系数是跟密度相关的,是比较可信的,即使可能最后不恰好与目标值相同,但相差绝对不会很大,这就可以让其误差小于很小的一个整数时停止,比如3,接下来直接跨过偶数,调用公式直至与N相同。第二个方面其实也很简单,x为第N个素数,只需要π(x)=N,π(x-1)=N-1即可,解决这个问题可以用两种方法,一种继续套用公式递减直至满足条件即可,另一种是递减判断出第一个素数为止,这里可以用米勒罗宾算法,不过这两种方法在N较小时相差不大,N较大时后者会有一定的优势。
以下是耗费时间,具体代码参见https://github.com/WBinke/PrimeFinder
时间: 2024-09-29 20:31:03