您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

在不确定的筛子上增加车轮分解

在不确定的筛子上增加车轮分解

赔率(即2互质数)是通过 “滚轮” 产生的[2],即通过从初始值3(类似于5、7、9 …)开始重复添加2,

n=3; n+=2; n+=2; n+=2; ...           # wheel = [2]
  3     5     7     9

通过重复相加2,然后4,再重复2,然后4等生成2-3-coprimes:

n=5; n+=2; n+=4; n+=2; n+=4; ...     # wheel = [2,4]
  5     7    11    13    17

在这里,我们确实需要知道从哪里开始添加与2或4之间的差异,具体取决于初始值。对于5、11、17 …,它是2(即车轮的第0个元素);对于7、13、19,…,它是4(即第一元素)。

我们怎么知道从哪里开始?滚轮优化的意义在于,我们仅处理此序列互质数(在此示例中为2-3-coprimes)。因此,在获得递归生成的质数的代码部分中,我们还将维护滚轮流,并对其进行推进,直到看到其中的下一个质数为止。滚动顺序将需要产生两个 结果- 数值和车轮位置。因此,当我们看到质数时,我们也获得了相应的车轮位置,并且可以从车轮上的该位置开始生成其倍数。p当然,我们将所有内容相乘,从开始P*p

for (i, p) # the (wheel position, summated value) 
           in enumerated roll of the wheel:
  when p is the next prime:
    multiples of p are m =  P*p;       # map (P*) (roll wheel-at-i from p)
                       m += P*wheel[i]; 
                       m += P*wheel[i+1];    ...

因此,字典中的每个条目都必须保持其当前值,其基本质数和其当前的车轮位置(在需要时,将其环绕度调整为0)。

为了产生结果质数,我们滚动另一个互质数序列,并仅保留字典中未包含的那些元素,就像参考代码中那样。

更新: 在codereview上进行了几次迭代(非常感谢那里的贡献者!)我已经到达此代码,并尽可能使用itertools来提高速度:

from itertools import accumulate, chain, cycle, count
def wsieve():  # wheel-sieve, by Will Ness.    ideone.com/mqO25A

    wh11 = [ 2,4,2,4,6,2,6,4,2,4,6, 6,2,6,4,2,6,4,6,8,4,2, 4,
             2,4,8,6,4,6,2,4,6,2,6, 6,4,2,4,6,2,6,4,2,4,2, 10,2,10]
    cs = accumulate(chain([11], cycle(wh11)))    # roll the wheel from 11
    yield(next(cs))       # cf. ideone.com/WFv4f,
    ps = wsieve()         # codereview.stackexchange.com/q/92365/9064
    p = next(ps)          # 11
    psq = P**2            # 121
    D = dict(zip(accumulate(chain([0], wh11)), count(0)))  # wheel roll lookup dict
    mults = {}
    for c in cs:          # candidates, coprime with 210, from 11
        if c in mults:
            wheel = mults.pop(c)
        elif c < psq:
            yield c
            continue
        else:    # c==psq:  map (P*) (roll wh from p) = roll (wh*p) from (P*p)
            i = D[(p-11) % 210]                 # look up wheel roll starting point
            wheel = accumulate( chain( [psq], 
                             cycle( [P*d for d in wh11[i:] + wh11[:i]])))
            next(wheel)
            p = next(ps)
            psq = P**2
        for m in wheel:   # pop, save in m, and advance
            if m not in mults:
                break
        mults[m] = wheel  # mults[143] = wheel@187

def primes():
    yield from (2, 3, 5, 7)
    yield from wsieve()

与上面的描述不同,此代码直接计算每个质数从何处开始滚动轮子,以生成其倍数

其他 2022/1/1 18:30:09 有633人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶