I have written a Python function am_i_wilson(P) that takes an integer P as input and checks if it is a Wilson prime. Here's how it works:
If the input P is equal to 0 or 1, the function returns False. Otherwise, it calculates (fact(P-1) + 1) / (P * P) using the fact() function, where fact(n) calculates the factorial of n. Finally, it checks if the result is a whole number using the whole_num() function, which returns True if the input is a whole number and False otherwise.
Here's the code:
def am_i_wilson(P):
if P == 1:
return False
if P == 0:
return False
return whole_num((fact(P-1) + 1) / (P * P))
def fact(n):
f = 1
while n > 0:
f *= n
n -= 1
return f
def whole_num(n):
return (n % 1) == 0
I'd appreciate any feedback or suggestions on how to improve the code. Thanks!
2 Answers 2
Just as information, note that the first three Wilson primes are 5, 13, 563, and the fourth Wilson prime is known to be greater than 2*1013.
Whatever the fourth Wilson prime is, am_i_wilson
won't be suitable to detect it. That number is just too high.
am_i_wilson
does not check whether P is a prime number, and may return True improperly when P is not prime but does pass the other condition.
Here are two things that you should probably know, at least so you can use them in different contexts:
- Checking whether X is divisible by Y typically should not be done by dividing X by Y and checking whether there is a fractional part, because the division may round a not-quite-integer to an integer. A proper way that works in general is checking
X % Y == 0
. - As an extension of that, if you're going to compute something and then check whether it's divisible by Y, you can (usually, but there are some restrictions) do the whole computation modulo Y, and check whether the result is zero. This has the advantage that the intermediate results do not become arbitrarily large. A factorial becomes very large very quickly, evaluating it modulo (in this case) P2 at least makes it a little bit more tractable, but even then it's too slow to detect the fourth Wilson prime.
There is already a function in the built-in module
math
to calculate factorials:import math math.factorial(x)
Wilson primes have to be prime of course, so you can use Wilson's theorem to check this. The only number that yields a false positive is
1
(returns undefined value for 0 as \$-1!\$ does not exist) , and these cases can be dealt with by usingand
:is_prime=lambda x:x>1 and (math.factorial(x-1)+1)%x==0
Wilson primes need to be integers as well:
is_prime=lambda x:x>1 and x%1==0 and (math.factorial(x-1)+1)%x==0
Wilson's theorem is closely related to Wilson primes, so you can edit that in using list comprehension and membership operators:
am_i_wilson=lambda x:x>1 and x%1==0 and (False not in [(math.factorial(x-1)+1)%y==0 for y in [x,x*x]])
if P == 0 or P == 1:
instead. \$\endgroup\$