【问题标题】:Prime number printer stops at 251, why? [duplicate]素数打印机停止在 251,为什么? [复制]
【发布时间】:2016-10-20 10:39:47
【问题描述】:

我今天开始学习 Python,我想创建一个程序来打印从 0 到 10 000 的所有素数。我设法让我的程序打印出直到 251 的所有素数,然后停止打印出数字。为什么会这样?

代码如下:

for numberToCheck in range(2,10000):
    divider = 2
    while numberToCheck > divider:
        if numberToCheck % divider is 0:
            break
        else:
            divider += 1
    if numberToCheck is divider:
        print(numberToCheck, "is a prime number.")

【问题讨论】:

  • 那个`(反引号)会导致语法错误。您可能需要编辑它并删除代码部分末尾的 `,除非它是用于格式化的标记。
  • 欢迎堆栈溢出!除了您的问题之外,您可以通过不检查大于numberToCheck 一半的数字的模数来使此功能的效率提高两倍。对于任何给定的numberToCheck,大于该数字除以二的数字不可能是它的除数之一。
  • @Alex 你不能把它限制在要检查的数字的平方根吗?
  • @Azor-Ahai 我想是的,是的!更高效:)

标签: python


【解决方案1】:

问题是您使用的是is 而不是==is 运算符执行 对象标识 比较,由于 实现细节,对于低于 256 的所有数字“可能会起作用”。 251 是 256 以下的最大素数(检查here,下一个素数是 257),然后is 返回False

>>> 254 + 1 is 255
True
>>> 255 + 1 is 256
True
>>> 256 + 1 is 257
False

相等运算符是==

>>> 254 + 1 == 255
True
>>> 255 + 1 == 256
True
>>> 256 + 1 == 257
True

【讨论】:

    【解决方案2】:

    使用== 来检查数字是否相等:

    for numberToCheck in range(2,10000):
        divider = 2
        while numberToCheck > divider:
            if numberToCheck % divider is 0:
                break
            else:
                divider += 1
        if numberToCheck == divider:
            print(numberToCheck, "is a prime number.")
    

    Is 运算符用于检查两个对象的id,而== 运算符用于检查它们的值。

    Python 为 -5256 之间的值实现了一个整数数组,当您在此范围内创建一个 int 对象时,您将获得对现有数组实现的引用。这就是为什么 id 在这个范围内的所有整数对象中是相同的,但对于这个范围之外的整数对象是不同的,如下所示:

    >>> a = -6
    >>> b = -6
    >>> a is b      # a and b has different id
    False
    
    >>> a = -5
    >>> b = -5
    >>> a is b      # a and b has same id
    True
    
    >>> a = 256
    >>> b = 256
    >>> a is b      # a and b has same id
    True
    
    >>> a = 257
    >>> b = 257
    >>> a is b      # a and b has different id
    False
    

    这就是原因,您的程序打印素数直到 251 而不是 next 素数 257 和之后,但是您的程序确实运行到 numberToCheck 到达 9999

    另外,您可以考虑使用更快的算法来生成素数,例如Sieve of Eratosthenes

    基本上,您应该检查numberToCheck2 和(之前找到的numberToCheck 的素数或平方根,以较小者为准)之间的所有素数 的可分性。

    【讨论】:

      【解决方案3】:

      错误在最后一个if。改成

      if numberToCheck is divider:
      

      if numberToCheck == divider:
      

      说明: is 测试引用是否相等,而 == 检查值的相等性(更具体地说,它在您的元素上调用 __eq__ 方法)

      第一个质数打印到 251 的原因是因为 python 缓存了所有小整数。

      例如:

      >>> 100 == 10**2
      True
      >>> 100 is 10**2
      True
      >>> 1000 == 10**3
      True
      >>> 1000 is 10**3
      False
      

      (示例取自here) 您应该只使用is 来检查引用(对象不仅应该相等,而且应该是相同的实例)或与None 进行比较。

      【讨论】:

        【解决方案4】:

        切勿将整数与is 进行比较。始终使用==

        == 应该用于比较数字。

        这里是固定代码:

        for numberToCheck in range(2,10000):
        divider = 2
        while numberToCheck > divider:
            if numberToCheck % divider == 0:
                break
            else:
                divider += 1
        if numberToCheck == divider:
            print(numberToCheck, "is a prime number.")
        

        【讨论】:

          【解决方案5】:

          问题是你使用了isis 不检查相等性,它检查对象的身份(内存地址);对象 a 是否与对象 b 相同?

          请参考以下问题:

          Is there a difference between `==` and `is` in Python?

          "is" operator behaves unexpectedly with integers

          Why (0-6) is -6 = False?


          解决你的问题:

          def prime(numberToCheck):
              divider = 2
              while numberToCheck > divider:
                  if numberToCheck % divider == 0:
                      break
                  else:
                      divider += 1
          
                  if numberToCheck == divider:
                      print(numberToCheck, "is a prime number.")
          

          这里有一点琐碎的说明,但在大型应用程序中可能很重要:我创建了一个名为 prime 的函数来最大限度地重复使用代码。现在您可以通过prime 函数来检查您喜欢的任何数字是否是素数,这比硬编码您要测试的数字要好得多!

          【讨论】:

            【解决方案6】:

            您不得将数字与is 进行比较。始终使用== 进行相等性测试。

            【讨论】:

              【解决方案7】:

              您使用的是 is 而不是 ==。 无论如何,代码明智的你正在浪费资源检查这样的素数。你应该只检查从 2 到 sqrt(n) 并且你应该最好保留质数并只检查它们直到你到达它们,例如你正在检查数字 41 是否是质数,检查质数 2 3 5 然后你知道它不是素数(因为素数和 sqrt 之间的所有其他数字都不是素数,所以您已经检查过它们) 随手创建一个素数列表。

              试试这个代码:

              import math
              primes = [2]
              for n in range(3,100):
                  for i in primes:
                      if n in primes:
                          break
                      if n%i == 0:
                          break
                      if i> math.sqrt(n):
                          primes.append(n)
                          break
              

              【讨论】:

                【解决方案8】:

                This link会帮助你为什么不使用is

                In [5]: a = 254+1
                
                In [6]: b = 255
                
                In [7]: a is b  # both are same objects
                Out[7]: True
                
                In [8]: id(a)
                Out[8]: 37644344 # id of a
                
                In [9]: id(b)
                Out[9]: 37644344   # same id as a
                

                对于 > 256

                In [10]: a = 256+1
                
                In [11]: b = 257
                
                In [12]: a is b # both are different objects but values are same
                Out[12]: False
                
                In [13]: id(a)
                Out[13]: 39721992 # id of a
                
                In [14]: id(b)
                Out[14]: 39722592 # new id created not same as a
                

                is 总是与对象而不是值进行比较

                为什么只有 256 个?

                来自python docs

                当前的实现为所有人保留一个整数对象数组 -5 到 256 之间的整数,当您在该范围内创建一个 int 时,您 实际上只是取回对现有对象的引用。

                当您分配 a=255 时,您只是将 a 添加为引用现有的 255。当 a=257 将创建新的 int 类型对象时

                【讨论】:

                  猜你喜欢
                  • 2021-12-15
                  • 1970-01-01
                  • 2015-02-15
                  • 2020-01-11
                  • 2023-01-11
                  • 2023-03-06
                  • 1970-01-01
                  • 2021-09-12
                  • 1970-01-01
                  相关资源
                  最近更新 更多