我已经编写了威尔逊素数的代码,并且我的代码适用于大多数数字,但是对于非常大的数字,它会给出 OverflowError:int太大而无法转换为浮点数。有什么方法可以为非常大的数字编写威尔逊素数代码。 主要问题是检查威尔逊素数威尔逊素数应满足以下条件。其中 P代表素数。
然后((P-1)!+ 1)/(P * P)应该给出一个整数。 正如您所看到的,阶乘涉及此过程,因此对于非常大的数字而言,这非常困难。
我的代码:
def am_i_wilson(n):
import math
n1 = math.sqrt(n)
n1 = math.ceil(n1)
c = 0
def fact(n):
num = 1
for i in range(2,n+1):
num = num*i
return num
if n <= 1:
return False
for i in range(2, n1 + 1):
if n%i == 0:
c+ = 1
if c != 0:
return False
x = (fact(n-1)+1)/((n**2)*1.0)
return x.is_integer()
在我的代码中,如果数字为Wilson Prime,则返回True,否则返回False。这里的 n 是要检查其是否为Wilson素数的数字。
答案 0 :(得分:1)
我认为这是最有效的方法
import math
def am_i_wilson(num):
if num < 2 or not all(n % i for i in range(2, num)):
return False
return (math.factorial(num - 1) + 1) % (num ** 2) == 0
或者您也可以尝试
import math
def am_i_wilson(n):
if n <= 2:
return False
fact=math.factorial(n-1)
#this conditional checks that the number is prime or not
#this condition is called wilson theorem in number theory
if (fact+1)%n==0:
x = (fact+1)%(n**2)
if x==0:
return True
else:
return False
else:
return False
答案 1 :(得分:0)
如果有人有更好的方法,请回答。
您的程序主要依赖于素数和计算阶乘的测试。您分离出阶乘逻辑,但嵌入了效率低下的素数测试-在知道数字不是素数之后,它将继续测试余数!我将两者分开,以便可以独立于Wilson Prime测试本身对它们进行测试和优化:
def factorial(n):
number = 1
for i in range(2, n + 1):
number *= i
return number
def am_i_prime(n):
if n < 2:
return False
if n % 2 == 0:
return n == 2
for divisor in range(3, int(n ** 0.5) + 1, 2):
if n % divisor == 0:
return False
return True
def am_i_wilson(n):
return am_i_prime(n) and (factorial(n - 1) + 1) % n ** 2 == 0
给定固定目标进行测试的更有效方法是实施主要的筛子,并在计算筛子时针对遇到的每个主要分子,测试其是否为威尔逊素数。
答案 2 :(得分:0)
我最近一直在试验优质筛。我对Robert William Hanks编写的其中一个进行了快速修改(即修改),并提出了这个建议。首先输出:
$ ./wilson_primes.py 10000
[5, 13, 563]
...所以我怀疑Wikipedia上有关Wilson素数的文章是正确的;-)
import sys
def fact(n):
num = 1
for i in range(2, n+1):
num *= i
return num
def is_wilson(n):
return (fact(n-1)+1) % n**2 == 0
def rwh_primes1(n):
""" Returns a list of primes < n """
sieve = [True] * (n/2)
for i in range(3,int(n**0.5)+1,2):
if sieve[i/2]:
sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)
# return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]
for i in range(1,n/2):
if sieve[i]:
p = 2*i + 1 # convert index to normal prime
if is_wilson(p): #
yield p #
if len(sys.argv) > 1:
N = int(float(sys.argv[1]))
else:
N = 10000 # default: 1e4 10,000
print [p for p in rwh_primes1(N)]
首先,我只尝试了fact()函数,并惊讶地发现它可以产生巨大的结果。但是,与原始的主筛相比,它非常慢。记住上一次计算的阶乘并重新使用它可以跳过下一次阶乘的一部分,也许可以使其运行得更快。
编辑
我更改了fact()来记住它的最后结果,如下所示:
last_fact = 1
last_n = 1
def fact2(n):
global last_fact, last_n
num = last_fact
for i in range(last_n+1, n+1):
num *= i
last_n = n
last_fact = num
return num
def is_wilson(n):
return (fact2(n-1)+1) % n**2 == 0
确实加快了速度。 cProfile显示is_wilson()现在是瓶颈。我想不出一种简单的方法来加快它的速度。