【问题标题】:Sieve of Eratosthenes leaving out some compositesEratosthenes 的筛子漏掉了一些复合材料
【发布时间】:2017-05-11 11:18:20
【问题描述】:

编辑:好的,所以代码现在可以工作了...谁能解释为什么将 Floor(1000/index) 更改为 floor(999/index) + 1 有帮助?

我对埃拉托色尼筛法的实现是在列表末尾列出一些复合材料作为素数。也就是说,如果我要找到 1000 之前的素数,则还包括 980 到 1000 之间的一些非素数

from math import floor

prime_list = []
list_primes2 = [True for x in range(1000)]
list_primes2[0], list_primes2[1] = False, False

for index, value in enumerate(list_primes2):
    if value:
        for x in range(floor(999/index)+1):
            list_primes2[index*x] = False

        prime_list.append(index)

print(prime_list)

上面的代码导致所有素数不超过 1000 加上 989 和 999

989 的质因数是 23 和 43,两者都在 prime_list 中列出

999 的质因数是 3 和 37,两者都在 prime_list 中列出

【问题讨论】:

    标签: python python-3.x sieve-of-eratosthenes


    【解决方案1】:

    想想什么时候index = 3。在这里,floor(1000/index) = 333range(333) 生成介于 0 和 332 之间的值。因此,list_primes2[999] 不会设置为 False

    另一方面,floor(999/index) + 1 = 334range(334) 产生介于 0 和 333 之间的值。

    一般来说,这个语句的结构应该是floor(max/index) + 1。请注意,ceil(max/index) 语句不是等效的。从上面的示例中可以很容易地看出这一点,其中ceil(max/index) 将再次生成介于 0 和 332 之间的值。

    【讨论】:

      【解决方案2】:

      我尝试弄乱1000 数字以查看它是否会表现出相同的行为,因为您只看到接近极限的错误输出,并且似乎错误的非素数保留在接近极限的列表中(无论你在哪里设置,我都尝试了 2000)。

      简短回答:问题似乎是由于range(float(1000/index)) 元素的运作方式,您正在削减接近上限的一些值。它没有遍历它们,也没有从你的素数列表中取出它们。

      如果将 1 添加到该范围内,它会起作用,也就是说,它会遍历它需要的所有数字,但您必须将 1000 减少到 999 以防止乘积上升到 1000 以上(即x in range(floor(1000/index)+1))。否则,该产品 >999 并引用超出您设置的原始范围的列表索引:list_primes2 = [True for x in range(1000)]

      更长的答案/我是如何到达那里的: 你的第一个 range(1000) 是 0, 1000。 你的第二个是range(floor(1000/index))ie 0, 1 我相信一定是这样,因为据我了解,floor() 会给您小于或等于 x 的最大整数值。 对于range(floor(1000/index)),范围永远不会大于一,因为它去了浮动(1000/999)给出范围0、1。 现在,如果你使用 `range(floor((999/index)+1) 你会以范围 0, 2 结束。

      现在正在试验,似乎如果你这样做 range(n), range(floor((n-1/index)+1) 就可以了。

      我为每次迭代打印了 x、index、product x*index 范围:对于您使用的第一组参数,它只是循环到 x=23,index=42,所以它永远不会返回 989,与 999 相同,它永远不会循环遍历等于 999 的 index 和 x 的任何组合。当您将范围增加 1 时,它会达到所有这些迭代。您必须将 1000 减少到 999 以防止产品升至 1000 以上(即x in range(floor(1000/index)+1))并引用超出您设置的原始范围的列表索引:list_primes2 = [True for x in range(1000)]

      from math import floor
      prime_list = []
      list_primes2 = [True for x in range(1000)]
      list_primes2[0], list_primes2[1] = False, False
      for index, value in enumerate(list_primes2):
          if value:
              for x in range(floor(1000/index)):
                  print (x)
                  print (index)
                  print (x*index)
                  print (range(floor(1000/index)))
      for index, value in enumerate(list_primes2):
          if value:
              for x in range(floor(1000/index)):
                  list_primes2[index*x] = False
              prime_list.append(index)
      print(prime_list)
      
      
      prime_list = []
      list_primes2 = [True for x in range(1000)]
      list_primes2[0], list_primes2[1] = False, False
      for index, value in enumerate(list_primes2):
          if value:
              for x in range(floor(999/index)+1):
                  print (x)
                  print (index)
                  print (x*index)
                  print(range(floor(999/index)+1))
      
      for index, value in enumerate(list_primes2):
          if value:
              for x in range(floor(999/index)+1):
                  list_primes2[index*x] = False
              prime_list.append(index)
      print(prime_list)
      

      进一步: 我认为您可能误解了 Sieve 的工作原理,或者该范围的实际工作原理。使用筛子,您将迭代次数少得多,尤其是当您向上时,这是它有用的一部分:您标记每个向上的素数的倍数,因此您无需对每个数字执行详尽的测试来找到它的复合性或素数。您只需消除每个连续素数的倍数 2*(1...n), 3*(1...n), [4 is already elim], 5*(1...n) 直到您到达 n .

      我们将转到 20,以便更清楚。只有倍数被“迭代”

      So  
      x-[Eliminating]               [All Eliminated]                
      2-[4,6,8,10,12,14,16,18,20]   [4,6,8,10,12,14,16,18,20]
      3-[6,9,15]                    [4,6,8,9,10,12,14,15,16,18,20]
      5-No more multiples <20       [4,5,6,8,9,10,12,14,15,16,18,20]          
      7-No more multiples <20       [4,5,6,8,9,10,12,14,15,16,18,20]
      11-No more multiples <20      [4,5,6,8,9,10,12,14,15,16,18,20]
      13-No more multiples <20      [4,5,6,8,9,10,12,14,15,16,18,20]
      17-No more multiples <20      [4,5,6,8,9,10,12,14,15,16,18,20]
      19-No more multiples <20      [4,5,6,8,9,10,12,14,15,16,18,20]
      

      所以我们可以看到 0-10 是 4 步,远远少于你的函数运行。

      我们可以像我之前的回答一样进行测试,即使我们将限制设置为低至 10 次,也可以进行 13 次迭代 - 比数字还多。

      from math import floor
      prime_list = []
      iterations=0
      list_primes2 = [True for x in range(10)]
      list_primes2[0], list_primes2[1] = False, False
      for index, value in enumerate(list_primes2):
          if value:
              for x in range(floor(9/index)+1):
                  iterations+=1
                  print ("Iterations:",iterations)
                  list_primes2[index*x] = False
                  print ("X:         ",x)
                  print ("index:     ",index)
                  print ("x*index:   ",x*index)
                  print(range(floor(9/index)+1))
                  print("Numbers now in list of primes: ",prime_list)
                  print()
              prime_list.append(index)
      
      print("List of primes: ",prime_list)
      

      【讨论】:

      • Range 只接受整数作为参数,因此是 floor 函数,无论如何,我通过将 1000/index 更改为 floor(999/index) + 1 来解决它。它现在可以工作了。我不知道如何或为什么。
      猜你喜欢
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 2016-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多