【问题标题】:Strange output when trying to find prime numbers Python尝试查找素数Python时的奇怪输出
【发布时间】:2021-04-20 18:36:23
【问题描述】:

好吧,我承认我是个菜鸟,而且我一直在学习关于 udemy 的编程课程。问题是要求编写一个函数来查找直到给定数字的所有素数。于是我开始写下面的代码来提取非偶数,以及不能被 3 整除的数字,刚刚开始:

def count_primes(num):
    num_list5 = []
    for i in range(num + 1):
        print(i)
        if i % 2 != 0 or i % 3 != 0:
            num_list5.append(i)
    
    return num_list5

当我调用 100 的函数时,例如: count_primes(100) 在输出中,我得到 num_list5 显示范围内的所有数字,但 6 和 6 的倍数除外:

[1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14 ...]

就像 if 语句在这里执行 AND 操作...因为 6 可以被 2 AND 3 整除。这是错误还是什么?还是我理解和/或操作不正确?

奇怪的是,它在某个时间点工作,在进行更改并恢复它之后,它开始这样做......

我正在使用 VSCode 和 Jupyter 笔记本,并在 Ubuntu 20.04 上尝试了 Python 3.8.5 64 位和 3.9.4 64 位

【问题讨论】:

  • 你的目标是让这个输出的素数小于或等于num吗?
  • 你的代码正在做它应该做的事情。您同时添加所有不能被 2 和 3 整除的数字,即 6 (2*3) 和 6 的所有倍数。它应该是 AND 而不是 OR。 6%2 != 0 是假的,6%3 != 0 也是假的,这就是为什么它们没有附加到列表中。
  • 嗯,这有点像是在做 AND。请记住,(NOT A OR NOT B) 等于 NOT(A AND B)。如果既能被 2 整除又能被 3 整除,则省略一个数字。

标签: python boolean primes


【解决方案1】:

i % 2 != 0 or i % 3 != 0 等于 not (i % 2 == 0 and i % 3 == 0)(德摩根定律)

应该是i % 2 != 0 and i % 3 != 0

【讨论】:

  • 是的,我应该看到这一点,因为我最近才开始研究离散数学和命题数学,但仍然看到它在这里表示是一个奇怪的概念,因为我认为 Python 会看第一次比较,如果为真将进入条件语句,如果为假,则进入第二次比较以查看其真/假
  • @ArturoCastillin 您对操作顺序很正确。在第一个为真后,它不会检查第二个,但当第一个为真时,这意味着允许通过每个奇数 (i % 2 != 0) ,如果它为假,则检查每个不可被整除的偶数3. 所以每个不能被 3 整除的偶数 + 所有奇数 = 除了 6 的倍数之外的所有数字
【解决方案2】:

如果您希望生成所有小于num 的素数,您应该遍历所有小于i 的数字j 并检查i%j 是否为零,而不仅仅是2 和3。

def count_primes(num):
    num_list5 = []
    for i in range(2, num + 1): # start at 2 because 1 and zero are not primes
        print(i)
        for j in range(2, i):
            if i%j == 0:
                break
        else:
            num_list5.append(i)
    
    return num_list5

if __name__ == "__main__":
    n = 100
    print(count_primes(n))

请注意,使用埃拉托色尼筛法,这可以更有效地完成:

import math

def count_primes_sieve(num):
    num_list5 = [False, False] + [True]*(num - 1)
    for i in range(2, math.ceil(math.sqrt(num)) + 1):
        if num_list5[i]:
            j = i * i
            while j < len(num_list5):
                num_list5[j] = False
                j += i
    return [i for i, p in enumerate(num_list5) if p]

if __name__ == "__main__":
    n = 100
    print(count_primes_sieve(n))

【讨论】:

  • 记住您只需要搜索到sqrt(i)。你不需要一路走到i
  • @TimRoberts ...我每次都忘记这一点。感谢您指出。
【解决方案3】:

我们知道一些关于素数的事实,您可以在程序中使用这些事实。负数,0 和 1 不是素数。 2 是唯一的偶数素数。素数只有它自己和 1 作为因数。从乘法我们知道如果 a x b = c 那么 a, b 之一是

这里有一些伪代码可以提供帮助:

function isPrime(num)
  // 1, 0, negatives not prime.
  if (num < 2)
    return false
  end if
  
  // 2 is the only even prime.
  if (num MOD 2 = 0)
    return (num = 2)
  end if

  // Try odd factors up to square root.
  limit <- 1 + sqrt(num)
  for (test <- 3; test < limit; test <- test + 2)
    if (num MOD test = 0)
      // Not prime, we have found a factor. 
      return false
    end if
  end for

  // If we get this far then num is prime.
  return true

end function

【讨论】:

    【解决方案4】:

    正如有人指出的那样,在弄清楚命题数学和德摩根定律之后,我能够使用 or 和 mod 运算符提出一个非常简单的解决方案,并且只经历一次序列:

    def count_primes(num):
    
        num_list5 = []
    
        for i in range(2, num + 1):
            if i == 2 or i == 3 or i == 5 or i == 7:
                num_list5.append(i)
            if not (i % 2 == 0 or i % 3 == 0 or i % 5 == 0 or i % 7 == 0):
                num_list5.append(i)
        
        return num_list5
    
    print(count_primes(100))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 2015-02-28
      相关资源
      最近更新 更多