当前位置: 首页 > 知识库问答 >
问题:

有人能帮我理解这个埃拉托色尼筛子的剧本吗?最后几行让我困惑

周意智
2023-03-14

好了,我明白了厄拉多塞筛子背后的原理。我试着自己写一个,但基本上失败了(我写了一个函数式的素数生成器,它不是很有效,也不是一个筛子)。我想我在理解数学上更有问题,但是编程也把我搞糊涂了。

import numpy as np

def primesfrom2to(n):
    sieve = np.ones(n/3 + (n%6==2), dtype=np.bool) 
    # print(sieve) for n = 10 returns [True, True, True] 

好了,把球棒注销我有点糊涂了。它正在生成一个真值列表,当它们被确定为复合值时,将逐渐被标记为假。我认为它是说不超过1/3的小于n的值是质数,但是增加一个modolus运算能得到什么呢?

    sieve[0] = False

将1标记为false?

    for i in range(int(n**0.5)//3+1):
        # print(i) for n = 10 returns 0 and 1 on separate lines

这是要检查的范围设置。没有一个数字的乘积大于其平方根。除以3 1是怎么回事?

        if sieve[i]:
            k=3*i+1|1
            #print(k) for n = 10 returns '5' doesn't change till it adds 7 at n = 50

好的,那么,如果sieve[i]为真(所以素数/尚未标记为复合?)那么3*i 1或1?这到底是如何工作的?它似乎正在生成素数,稍后将乘以删除所有后续产品,但我不知道如何操作。

            sieve[      ((k*k)/3)      ::2*k] = False
            sieve[(k*k+4*k-2*k*(i&1))/3::2*k] = False

好的,这两个都是取素数k并标记它们的所有进一步倍数?如果n=5,这不会导致筛分[8.33::10]=False吗?另一个像筛子[41.3::10]?我就是不明白。

print(np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)])

好的,最后实际生成素数列表。再问一次,乘以3是怎么回事?显然,这段html" target="_blank">代码中有一些关于3的基本内容我不明白。同样,我也没有理解< code>|1的概念。

哦,只是为了好玩,这是我有效且非常低效的尝试。

import numpy
def sieve(num):

    master = numpy.array([i for i in range(2, num+1)])
    run = []
    y=2


    while y <= ((num+1)**(1/2)): 
        thing = [x for x in range(y, num+1, y) if x > 5 or x == 4]
        run = run + thing
        y = y+1 
    alist = numpy.in1d(master, run, invert = True)
    blist = (master[alist])
    print(blist)

计算500000个素数需要57秒。我正在做2000000个素数的欧拉求和问题。

共有1个答案

南门野
2023-03-14

这是numpy中的一个简单筛选算法:

import numpy as np
def sieve(Nmax):
    """Calculate prime numbers between 0 and Nmax-1."""
    is_prime = np.ones(Nmax, dtype=bool)
    Pmax = int(np.sqrt(Nmax)+1)
    is_prime[0] = is_prime[1] = False
    p = 2
    dp = 1
    while p <= Pmax:
        if is_prime[p]:
            is_prime[p*2::p] = False
        p += dp
        dp = 2
    primes = np.argwhere(is_prime)[:,0]
    print(primes)

sieve(100)    

如果我删除print语句,它将在我的普通笔记本电脑上以2.5秒的速度运行Nmax=10^8。

此算法的效率有点低下,因为它需要存储偶数值的素数和 3 的倍数。您可以通过过滤掉这些来节省存储空间,以便跟踪任何整数n的n * 6 1和n * 6 5的素数

关于您的问题:

  • (n%6==2)是布尔值,将被解释为0或1,并将添加一个元素以防止出现“off-by-one”错误。
  • int(n**0.5)//3 1应读作int(int(n**0.5)/3)1。除法先于加法。除以3是为了只为6n 1和6n 5值分配空间。
  • k=3*i1|1表示k=3*i 1(3*i 1)|1。因此,如果数组索引[0,1,2,3,4,5,…],则它们表示数字[1,5,7,11,13,17,…]
  • 对于表示6n 1和6n 5的元素,分别将筛选元素设置为False,这就是为什么有两个赋值。
  • 如果在Python 2.7中运行此命令,整数除法总是被截断,因此9/2将得到4。在Pythin 3中,最好使用//运算符来进行整数除法,即(k*k)/3应该是(k*k)//3

编辑:您可能希望归因于您询问的算法:列出N以下所有素数的最快方法。

 类似资料:
  • 我正在为厄拉多塞的筛子用Python写一个素数程序。虽然看起来很管用,但是很慢。我该如何加快速度呢? 更新:由于答案的帮助,我用布尔值而不是数字重写了代码。低于100000的列表现在运行时间不到6秒。

  • 我正在尝试对厄拉多塞的筛子进行并行实现。我做了一个布尔列表,对于给定的大小,用true填充。无论何时发现一个素数,该素数的所有倍数在布尔列表中都被标记为假。 我试图使这个算法并行的方法是在仍然过滤初始质数的同时启动一个新线程。例如,算法从素数 = 2 开始。在 for 循环中,当素数 * 素数时,我做另一个 for 循环,其中检查素数 (2) 和素数 * 素数 (4) 之间的每个数字。如果布尔列表

  • 我的任务如下:使用埃拉托斯特尼筛来定位并打印出从1到1000的所有素数。 遵循与此类似的过程: < li >按顺序写下所有需要考虑的数字。 < li >划掉1,因为它不是质数。 < li >转到未删除的下一个号码;留下它,但是划掉那个数字的所有倍数。 < li >重复步骤3,直到您超过所考虑的最大值的一半。在这一点上,所有没有被划掉的数字都是期望的素数。 您的算法可能与上述算法略有不同,但速度很重

  • 就像这个问题一样,我也在厄拉多塞的筛子上工作。同样来自《c语言编程原理和实践》一书的第4章。我能够正确地实现它,并且它的功能完全符合练习的要求。 现在,我怎样才能在输入的中处理真正的大数字?类型应该允许我输入2^32=4,294,967,296的数字。但是我不能,我运行内存溢出。是的,我已经计算过了:存储2^32量的int,每个32位。所以32/8*2^32=16 GiB的内存。我只有4 GiB…

  • 我试图找到素数使用厄拉多塞筛位数组,但我使用的是无符号整数数组。我需要能够产生多达2,147,483,647个素数。我的代码工作正常,可以生成大约10,000,000个,但是当我增加数组的大小以容纳更大的数字时,它失败了。有人能指导我如何用c语言(不是c语言)使用位向量吗?谢谢 这是我的代码:

  • 我正在尝试让我的埃拉托斯特尼筛程序仅输出用户请求的前n个素数。Sieve本身工作得很好 - 它正确地输出了前100个素数(如下面的数组所示),但是最后一个循环中的计数器变量无法正常工作,我无法找出原因。例如,如果用户输入“5”表示 n,则只会打印前 3 个定焦值。 有人可以帮我找出我的错误吗?我的目的是让“count”成为一个非常简单的计数器,每次都会增加1,直到它达到n。