1
\$\begingroup\$

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!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can do if P == 0 or P == 1: instead. \$\endgroup\$ May 8, 2023 at 6:10

2 Answers 2

6
\$\begingroup\$

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) P² at least makes it a little bit more tractable, but even then it's too slow to detect the fourth Wilson prime.
\$\endgroup\$
1
  • \$\begingroup\$ Thank You very good expliquation \$\endgroup\$
    – XMehdi01
    May 6, 2023 at 22:49
3
\$\begingroup\$
  1. There is already a function in the built-in module math to calculate factorials:

    import math
    math.factorial(x)
    
  2. 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 using and:

    is_prime=lambda x:x>1 and (math.factorial(x-1)+1)%x==0
    
  3. 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
    
  4. 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]])
    
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.