我认为这在技术上是轮分解。我正在尝试重新压缩我的程序对埃拉托斯特尼筛法的表示,它只包含可能是素数的数字索引。
一些背景:
最基本的轮子是[2]:跟踪2作为第一个素数,并且筛子仅包含奇数索引。 (50%))
下一个轮子是[2 3]:记录2和3作为第一个素数,筛子仅包含2*3=6之间的间隙(即1和5)。索引的形式为 6k+1 和 6k+5。 (33%)
下一个轮子是[2 3 5]:跟踪2、3和5作为第一个素数,筛子只需要8位来表示大小为30的间隔。(27%)
当清除数字的倍数位时,我使用此循环找到这些倍数:
def multiplesIndices (self, i):
for gap in self.gaps[1:]:
ret = i * (self.product * 0 + gap)
if ret > len (self): break
yield ret
for k in xrange (1, len (self) / i / self.product + 1):
for gap in self.gaps:
ret = i * (self.product * k + gap)
if ret > len (self): break
yield ret
问题在于设置车轮所需的时间,以及压缩比的收益递减。好吧,改变到不同的车轮尺寸需要大量的重新计算。另外,通过改变轮子尺寸,我认为我可以影响渐近复杂度。
所以我提出的解决方案是使用小轮子来初始化较大的轮子: [2 3] (6/2) 获取 [2 3 5] (30/8) 轮中的间隙 [2 3 5] 获取 [2 3 5 7] (210/48) 轮中的间隙
我需要帮助的地方是将已经计算的小筛子映射到要计算的大筛子,这样我就可以避免重新筛选从1开始的所有内容。获取前30个素数,用它们找到接下来的210-30个素数,用它们来找到接下来的 480-210 个素数。
更具体地说,我需要帮助反转此函数(或正确实现 invIndexOf()):
def indexOf (self, n):
if not self.isValidIndex (n): raise Exception ()
ret = n / self.product * len (self.gaps) + self.gaps.index (n % self.product)
assert n in self.invIndexOf (ret)
return ret
而且,自从我计算出任何事物的渐近复杂性以来,已经有几年了。我很确定这是一种改进,尽管不是很大。