【发布时间】:2020-03-22 16:37:33
【问题描述】:
我实现了Lucas-Lehmer primality test 来检查python 中的梅森素数。然后我使用 Cython 来加快计算速度。
- 原始 Python 代码:
def lucas_lehmer(p):
if p == 2:
return True
s = 4
M = (1 << p) - 1
for i in range(p-2):
s = ((s * s) - 2) % M
print("Processed: {}%".format(100*i//(p-2)))
if s == 0:
return True
else:
return False
- Cython 代码:
cpdef lucas_lehmer(int p):
if p == 2:
return True
cdef unsigned long long int M
M = (1 << p) - 1
cdef unsigned long long int s
s = 4
cdef int i
for i in range(p-2):
s = ((s * s) - 2) % M
print("Processed: {}%".format(100*i//(p-2)))
if s == 0:
return True
else:
return False
运行原始 Python 代码,它可以正常工作。但是对于 Cython,它只在 p = 31 和更低的情况下是正确的,在p = 61 和更大的情况下进行测试(所有测试的 p 值都是 2^p-1 是素数的值),它返回 False(不是素数),@987654328 除外@。
对于一些像97这样的p,即使2^97-1不是质数,程序实际上返回True(是质数),这是矛盾的。
为什么会这样?不对变量M和s使用cdef,计算是正确的,但性能不会有任何提高。
【问题讨论】:
-
为什么Python代码中有
M参数,如果它被立即覆盖? -
这肯定只是一些溢出?你是在问它到底发生在哪里?
-
M = (1 << p) - 1你认为M是如何存储的?也许您应该尝试定义 Cython 和 C 可以理解的类型。 StackOverflow 和其他地方的示例展示了如何为 Cython 定义 128 位整数。 -
但是,对于 p>64(或 p>128),您将需要使用支持任意大小整数的库(或使用 Python-integer,这不是一个坏选择)。