python123在线编制_Python123

分段埃拉托色尼筛

第100篇我选择分段埃拉托色尼筛用以在Cython中实现10⁹内的素数。这一次是为了提供一个尽可能快的算法。

我之所以偏离Python和通常的实现类型有几个原因。先不说其他的原因,我喜欢打破规则和优化。但是什么是最重要的…?

在大多数的文章里,我都尽可能地提供精简的算法。我知道算法可以改进但是我没有这样做,因为这需要再增加4或5行代码,以上都是我的推测。

我见许多人都在谈论时间复杂性,并目睹了他们对渐近线符号是如何工作的普遍错误的理解。

我也见过很多理解得不错的人,而且他们的证据(不是教科书上的)支持我的观点。

从理论上来说,对大O符号的分析从下面算法的一个理论计算模型开始,以研究它与数据相关的行为。关于算法,f(N)=O(g(N)表示,对于足够大的数据,算法f最多需要算法g所要求的步骤数。而f可以除以任何正常数来证明这个说法是正确的。

若果你感兴趣的话,可以看看我的摊销算法分析,这里举了一个关于复杂度分析的栗子。

事实上,在实践中,大O表示法的工作方式不同。给定了解决同一问题的两种算法,那么时间复杂度为O(n.log n)的算法的性能比时间复杂度为O(n²)的算法要差。你的大部分数据也不太可能是这样的。

我已经在本系列中提及了这个话题。编写一个在任何情况下性能都好的复杂算法几乎是不可能的。标准库通常是在理想条件下表现良好和在特殊情况下仍然适用而编写的。

例如,如果你需要定期对数据进行排序,而你的数组只有几十个项,内置排序可不是最佳的算法。你可以做很多次的加速,但总时间是基本不变的,那么你就不需要再花心思在这上了。这说明这个算法表现良好。

如果你需要定期对数百万条记录进行排序,那么调用内置排序可能是你所做过的最糟糕的事情。最好去使用不同的数据结构(如二进制搜索树)来避免批排序。

也可能不是。我自己的证据表明,性能最好的算法通常是你对它期望最少的算法。你可以试着给它一个机会。

在实践中,复杂性分析总是用分析器开始的。

编写引用实现,让分析器显示出你任何的瓶颈。再考虑一下改进,然后一次又一次地改进和剖析。

这就是我实现分段埃拉托色尼筛。我确定了关键函数,并为每个函数编写了几个实现方式,然后检查了结果。

分段埃拉托色尼筛背后的主要思想是,现代CPU不能寻址一个字节,甚至不能寻址一个整数。CPU有几层高速缓存,每当你在内存中的任何地方寻址时,它都必须首先取这部分并将其存储在缓存中。

这需要花费大量的时间,分段埃拉托色尼筛寻址广泛的连续内存区域是非常浪费的。幸运的是,该算法可以重写为在适合CPU高速缓存的本地段中筛选素数。

这一增益是巨大的,我的算法实现能够找到10⁶以内的素数的时间约为6毫秒。10⁹以内的素数可在约8秒内找到。作为参考,我的机器版本是MacBookPro 2014,2.2GHzi7。

如果你使用的是Anaconda发行版,这个笔记本将工作良好。如果不是,需要运行算法的哈,请执行以下步骤:确保安装了Cython。

创建文件day100.pyx并将代码放入其中。不要忘记删除%%cython指令

创建并使用运行文件main.py。代码如下:

算法实现

测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值