简体   繁体   中英

Shorter way to test if prime number

To test if a number is prime, I do:

def isprime(n):

    if n < 2: return False

    for i in range(2, n):
        if n % i == 0:
            return False
    else:
        return True

I wonder how to make that more efficient/shorter to write.

With generator:

def isprime(n):
    return (all(False for i in range(2,n) if n % i == 0) and not n < 2)
    
print (isprime(0))
print (isprime(1))
print (isprime(2))
print (isprime(3))
print (isprime(9))
print (isprime(10))
print (isprime(13))

Output:

False
False
True
True
False
False
True

Alongside @Théophile's suggestion, I'd add the following recommendations:

  1. Test whether a number is even and greater than 2 before even calling is_prime (eliminating the need for a function call).

  2. Instead of range(2, n) , use range(3, n, 2) . This will consider only odd numbers; the third parameters of range is the step by which you'll increment.

  3. Instead of looping through all the integers (or all the odd integers) less than the square root of n, create a cache of the prime numbers you've already found and loop through them. One of the fastest and most elegant ways to do this is using functools.lru_cache , but it will suffice simply to write provide a cache yourself.

Here's a quick and dirty way of doing this that is longer but more efficient than your original proposal:

from math import sqrt

# We seed the cache with the first two odd primes because (1) it's low-
# hanging fruit and (2) we avoid the need to add extra lines of code (that
# will increase execution time) for cases in which the square roots of numbers
# are less than any primes in the list
odd_primes = [3, 5]

def is_prime(n):
    
    # If n is not prime, it must have at least one factor less than its square 
    # root.
    max_prime_factor_limit = int(sqrt(n))
    
    # use a generator here to avoid evaluating all the qualifying values in 
    # odd_primes until you need them. For example, the square root of 27 is
    # 5.1962, but, since it's divisible by 3, you'll only test if 27 is prime
    # one time. Not a big deal with smaller integers, but the time to compute
    # the next prime will increase pretty fast as there are more potential
    # factors.
    
    available_primes = (p for p in odd_primes if p <= max_prime_factor_limit)
    
    for prime in available_primes:
        if n % prime == 0:
            return False
    
    return True


for i in range(7, 99, 2):
    # if no prime factors were found, add to cache
    if is_prime(i):
        odd_primes.append(i)
        
print(odd_primes)

There are additional things you can do to speed this up. The one that immediately springs to mind is, instead of calculating the square root of each number you're checking, use the squares of the primes to determine the upper limit of the set of primes you'll check. In other words, if you know that the square of 169 is 13, so you know that any number greater than 169 and less than 289 (the square of 17) will have a prime factor <= 13. You can also use that to save time by calculating the list of prime factors and passing the list to the function you're using to determine if an integer is prime. Note, of course, that this will only work if you're actually creating a list of primes.

number = int(input('please enter a number:'))
if number>1:
    for numbers in range(2, number):
        if (number % numbers) ==0:
            print(f"{number} is not a prime number")
         
            break
    else:
        print(f"{number} is a prime number")  
else:
    print(f"{number} is not a prime number")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM