素数打印机停止在 251,为啥? [复制]
Posted
技术标签:
【中文标题】素数打印机停止在 251,为啥? [复制]【英文标题】: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
,大于该数字除以二的数字不可能是它的除数之一。
"is" operator behaves unexpectedly with integers, Is there a difference between ==
and is
in Python?的可能重复
@Alex 你不能把它限制在要检查的数字的平方根吗?
@Azor-Ahai 我想是的,是的!更高效:)
【参考方案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 为 -5
到 256
之间的值实现了一个整数数组,当您在此范围内创建一个 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。
基本上,您应该检查numberToCheck
与2
和(之前找到的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】:问题是你使用了is
。 is
不检查相等性,它检查对象的身份(内存地址);对象 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 类型对象时
【讨论】:
以上是关于素数打印机停止在 251,为啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Banana 在 JavaScript 中打印? [复制]