python 素数最快_如何编程最快速度求出两百万以内素数个数(不限语言和算法)?...

填坑了。

之前说到,2 和 3之后,所有质数都必须满足6 n ± 1这个条件。所以利用这原理,可以提升三倍性能。这公式怎么来的呢?

首先我们知道,2以后的质数都必须是奇数,公式表达就是2n + 1,当然用2n - 1也行。

我们要把能整除3的过滤掉。即 2n + 1 不能整除3。我们做适当转换:

2n + 1 => 3n - n + 1

可见,我们只要确保1 - n不能整除3就可以。

令 n = 3 m + x,则有2 * (3m + x) + 1 => 6m + 2x + 1 ,x 的取值范围为 0 和 2。

所以得到,6m + 1 或者 6m + 5,其中6m + 5 等同于 6m - 1,只是m取值范围不同。

证明完毕。

同样,当我们有了6n ± 1之后,怎么去除 5和7 的倍数呢?刚好就这么巧:

6n ± 1 => 5n + n ± 1

6n ± 1 => 7n - n ± 1

懂了吧,剩下展开就行了。实测下,把3倍数过滤掉,用欧拉确实获得巨大的性能提升。

再把5倍数过滤掉,还能提升一点。到再过滤7倍数的时候,优势就有点看不到了,原因是,5级过滤到7级过滤,计算总量是从8/30 降到 48/210,节约率相比原始来说才3.8%,收益不多。

说好的代码呢?呃,上吧,F# 的代码。

let getPrimers maxValue =

let table = [|0uy; 2uy; 6uy; 8uy; 12uy; 18uy; 20uy; 26uy; 30uy; 32uy; 36uy; 42uy;

48uy; 50uy; 56uy; 60uy; 62uy; 68uy; 72uy; 78uy; 86uy; 90uy; 92uy;

96uy; 98uy; 102uy; 110uy; 116uy; 120uy; 126uy; 128uy; 132uy; 138uy;

140uy; 146uy; 152uy; 156uy; 158uy; 162uy; 168uy; 170uy; 176uy; 180uy;

182uy; 186uy; 188uy; 198uy; 200uy|]

let check = Array.zeroCreate (maxValue + 1)

let prime = Array.zeroCreate (maxValue / 210 * 48 + 48)

prime.[0]

prime.[1]

prime.[2]

prime.[3]

let rec loop n count step =

let i = n + int32 table.[step]

if i <= maxValue then

let count =

if not check.[i] then

prime.[count]

count + 1

else

count

let rec loopPrime j =

if j < count then

let comp = i * prime.[j]

if comp <= maxValue then

check.[comp] 0 then

loopPrime (j + 1)

loopPrime 4 // 把0 改为 4,这一步很重要,因为原理上杜绝了 2357倍数的检查, // 所以直接不用标注, 2000万数据测试下,节约了1/4时间 if step + 1 = table.Length then

loop (n + 210) count 0

else

loop n count (step + 1)

loop 11 4 0

===================================

看完一圈,没有一个好打的。

就抄个公式出来了事。那些所谓擅长数学的,怎么不知道2和3之后,所有质数都必须满足6 n ± 1这个条件?因为只有6 n ± 1才能避开2和3的倍数。 欧拉筛法改一下,速度一下子提到3倍了。即使你真的不懂,也该知道2之后,所有质数都是奇数吧?也能从原来提升两倍速度了。如果你想,数组也可以趁机把数组开小一点。优化都没尝试过就说这个算法内存占用什么的。。。。。

不才还有个「210里面中检测48个可能位置的」,也就是说,从开始就排除2、3、5、7的倍数。大概能提升到4倍(略低于4倍)。原理和代码稍晚放出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值