我从Fibonacci生成素数如下(使用Python
,mpmath和sympy获得任意精度:
from mpmath import *
def GCD(a,b):
while a:
a, b = fmod(b, a), a
return b
def generate(x):
mp.dps = round(x, int(log10(x))*-1)
if x == GCD(x, fibonacci(x-1)):
return True
if x == GCD(x, fibonacci(x+1)):
return True
return False
for x in range(1000, 2000)
if generate(x)
print(x)
它是一个相当小的算法,但似乎生成所有素数(除了5
以某种方式,但这是另一个问题)。我说似乎是因为很少的百分比(1000%以下0.5%和10K以下0.16%,越来越少)并不是素数。例如,在1000:323下,还生成377和442。这些数字不是素数。
我的脚本中是否有其他内容?我尝试通过将.dps
设置与正在计算的数字相关联来说明精确度。 斐波那契和素数似乎真的是如此相关,但是当它得到详细时它们就不是吗? :)
答案 0 :(得分:2)
对于此类问题,您可能需要查看gmpy2库。 gmpy2
提供对GMP多精度库的访问,该库包括gcd()和fib()函数,它们可以快速计算最大公约数和第n个斐波纳契数,并且只使用整数运算。
以下是您重新编写的程序以使用gmpy2
。
import gmpy2
def generate(x):
if x == gmpy2.gcd(x, gmpy2.fib(x-1)):
return True
if x == gmpy2.gcd(x, gmpy2.fib(x+1)):
return True
return False
for x in range(7, 2000):
if generate(x):
print(x)
您不应该使用任何浮点运算。您只需使用内置%
(模数)运算符即可计算GCD。
<强>更新强>
正如其他人评论的那样,您正在检查Fibonacci pseudoprimes。实际测试与您的代码略有不同。让我们调用正在测试的号码n
。如果n
可被5整除,那么如果n
均分fib(n)
,则测试通过。如果n
除以5会留下1或4的余数,那么如果n
均分fib(n-1)
,则测试通过。如果n
除以5会留下2或3的余数,那么如果n
均分fib(n+1)
,则测试通过。您的代码没有正确区分这三种情况。
如果n
均分另一个数字,比如x
,则会留下0的余数。这相当于x % n
为0.计算{{1}的所有数字斐波纳契数不是必需的。测试只关心其余部分。您可以计算每一步的余数,而不是将斐波纳契数计算为全精度。以下代码仅计算Fibonacci数的余数。它基于Python mpmath not arbitrary precision?
n-th
它是用纯Python编写的,非常快。
通常称为斐波那契数的数字序列只是一般卢卡斯序列def gcd(a,b):
while b:
a, b = b, a % b
return a
def fib_mod(n, m):
if n < 0:
raise ValueError
def fib_rec(n):
if n == 0:
return 0, 1
else:
a, b = fib_rec(n >> 1)
c = a * ((b << 1) - a)
d = b * b + a * a
if n & 1:
return d % m, (c + d) % m
else:
return c % m, d % m
return fib_rec(n)[0]
def is_fib_prp(n):
if n % 5 == 0:
return not fib_mod(n, n)
elif n % 5 == 1 or n % 5 == 4:
return not fib_mod(n-1, n)
else:
return not fib_mod(n+1, n)
的特例。通常的斐波那契数字由L(n) = p*L(n-1) - q*L(n-2)
生成。 (p,q) = (1,-1)
接受p,q的任意值。 gmpy2.is_fibonacci_prp()
应与上面给出的gmpy2.is_fibonacci(1,-1,n)
的结果相符。
免责声明:我维持gmpy2。
答案 1 :(得分:1)
这不是一个Python问题;这是一个数学/算法问题。您可能希望在Math StackExchange上询问它。
此外,无需任何非整数算术:您可以使用纯整数数学轻松完成计算floor(log10(x))
。使用任意精度数学将大大减慢此算法的速度,并可能引入一些奇怪的数字错误。
这是一个简单的floor_log10(x)
实施:
from __future__ import division # if using Python 2.x
def floor_log10(x):
res = 0
if x < 1:
raise ValueError
while x >= 1:
x //= 10
res += 1
return res