def test_prime(n):
q = True
for p in range(2,n): #Only need to check up to rootn for primes and n/2 for factors
if int(n%p) is 0:
q = False
print(p, 'and', int(n/p), 'are factors of ', n)
if q:
print(n, 'IS a prime number!')
else:
print(n, 'IS NOT a prime number')
我刚刚开始玩Python,我正在整理一些零碎的东西来消磨时间。我一直在玩质数测试,并有想法显示非素数的因素。我上面列出的函数似乎运行得很好,除了输出不一致。
e.g。如果我设置n = 65432我得到......
2 and 32716 are factors of 65432
4 and 16358 are factors of 65432
8 and 8179 are factors of 65432
8179 and 8 are factors of 65432
16358 and 4 are factors of 65432
32716 and 2 are factors of 65432
65432 IS NOT a prime number
这是我所期待的。但是如果我设置n = 659306我得到......
2 and 329653 are factors of 659306
71 and 9286 are factors of 659306
142 and 4643 are factors of 659306
4643 and 142 are factors of 659306
9286 and 71 are factors of 659306
659306 IS NOT a prime number
这是不同的,因为它最后不包括因子329653。这不是问题,因为所有因素都显示在某个地方,但令我讨厌的是我不知道为什么这会发生在一些数字上!
只是为了告诉你我不是一个完整的白痴,我已经知道这似乎只发生长度超过5个字符的整数值。有人可以告诉我为什么这两种情况的输出不同吗?
答案 0 :(得分:10)
您需要n % p == 0
,而不是n % p is 0
。 is
测试身份,而不是相等,而不是每0 与其他0相同。
>>> 659306 % 329653
0
>>> (659306 % 329653) == 0
True
>>> (659306 % 329653) is 0
False
>>> id(0)
136748976
>>> id(659306 % 329653)
3070888160
id
基本上对应于内存中的位置。
这样想:如果你有一个加元,我有一个加元,那么它们在价值上是相等的(1 == 1),但它们不是同一个物体(我的一美元)硬币与你的一美元硬币不一样。)我们可以共享相同的硬币,但我们没有必要这样做。
[PS:您可以使用n//p
代替int(n/p)
进行整数除法。]
答案 1 :(得分:3)
幕后发生的事情有点复杂。我的评论专门适用于CPython
。其他实现,如PyPy,Jython,IronPython等,表现不同。
为了减少内存使用并提高性能,CPython会缓存一系列小整数,并尝试返回对这些对象的引用,而不是创建具有相同值的另一个整数对象。将数字与is
进行比较时,实际上是在检查CPython是否返回了对同一缓存对象的引用。但有时CPython不检查值是否是缓存的整数之一。怎么会发生这种情况?
我将解释CPython 3,因为它比CPython 2容易一些.CPython中可见的int
类型实际上在解释器内部称为PyLong
。 PyLong
将整数存储为digits
的数组,其中每个数字介于0和2**15-1
(32位系统)或0和2**30-1
(64位系统)之间。随着数字变大,数组的大小也会增大;这允许有效的无限整数。在计算%
时,CPython会检查第二个参数是否为digit
长。如果是这样,它会调用一个返回digit
的C函数(divrem1)作为结果。接下来,调用PyLong_FromLong
将适合C long(即divrem
的返回值)的值转换为PyLong。 PyLong_FromLong
检查参数是否在缓存的整数范围内,如果可能,将返回对缓存整数的引用。
如果第二个参数长度超过一个digit
,则调用另一个C函数(x_divrem)。 x_divrem
使用通用任意精度除法算法来计算余数。由于x_divrem
在计算过程中创建了一个PyLong
来存储余数,因此避免创建另一个重复整数没有任何好处;它已经存在。对于具有随机大数的计算,余数很少等于其中一个缓存的整数,因此进行检查不值得花费时间。
还有其他方法可以创建缓存整数的重复副本。我刚刚分析了问题中的一个。
这就是为什么你不使用is
来检查数字相等.....