0

I wrote this python code about 3 days ago, and I am stuck here, I think it could be better, but I don't know how to improve it. Can you guys please help me?

# Function
def is_prime(n):
    if n == 2 or n == 3:
        return True

    for d in range(3, int(n**0.5), 2):
        if n % d == 0:
            return False

    return True
Olivier Melançon
  • 19,112
  • 3
  • 34
  • 61
Locked
  • 51
  • 7
  • I would recommend reading up on Prime Sieve – Ilan Keshet Jun 08 '18 at 02:19
  • 2
    You have a couple indentation errors, and indentation is very important in Python – user3483203 Jun 08 '18 at 02:19
  • [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) – Barmar Jun 08 '18 at 02:20
  • Have a look at https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n/2068548#2068548 or https://stackoverflow.com/questions/1801391/what-is-the-best-algorithm-for-checking-if-a-number-is-prime/1801446#1801446 – Mr. T Jun 08 '18 at 08:24
  • It depends how big the numbers are, and whether you just want to test a single number (or just a few numbers), or if you need to test a whole bunch of numbers that lie within a range. In the 1st case, your code is fine, in the latter case you should use a sieve, possibly a segmented sieve. – PM 2Ring Jun 08 '18 at 11:01
  • 2
    To test very large numbers you can use Miller-Rabin. Most implementations of that test are probabilistic for large numbers, but it's possible to do it deterministically. You can determine the primality of all n < 3,317,044,064,679,887,385,961,981, with these witnesses: (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41). – PM 2Ring Jun 08 '18 at 11:07

2 Answers2

2

A good deterministic way to find relatively small prime numbers is to use a sieve.

The mathematical principle behind this technique is the following: to check if a number is prime, it is sufficient to check that it is not divisible by other primes.

import math

def is_prime(n):
    # Prepare our Sieve, for readability we make index match the number by adding 0 and 1
    primes = [False] * 2 + [True] * (n - 1)

    # Remove non-primes
    for x in range(2, int(math.sqrt(n) + 1)):
        if primes[x]:
            primes[2*x::x] = [False] * (n // x - 1)

    return primes[n]

    # Or use the following to return all primes:
    # return {x for x, is_prime in enumerate(primes) if is_prime}

print(is_prime(13)) # True

For reusability your could adapt the above code to return the set of all prime numbers up to n.

Olivier Melançon
  • 19,112
  • 3
  • 34
  • 61
  • I tried this, but to find if a large number is prime, this method would actually slow the code, since it would have to find even another prime numbers, so: If n is 500, it would check every prime less than 500, and compare it. Sorry if I didn't mentioned I was looking for big numbers – Locked Jun 08 '18 at 02:58
  • @Locked You seem to misunderstand primes. The only deterministic way to check if a number is prime is to check its divisibility by other primes. This solution is the same as what sympy.isprime does and in particular: *it is faster*. – Olivier Melançon Jun 08 '18 at 03:06
  • I see, but at least in my device, using sympy or even using the code that I first used is faster. To check every number between 1 and 1000000, here's the results: First code: About 3 seconds Sympy: About 2 seconds Using this method: More than 5 minutes – Locked Jun 08 '18 at 04:32
  • 1
    @Locked as stated, if you need to test for multiple numbers, just return the set of all primes, then one call is sufficient. sympy probably caches its sieve – Olivier Melançon Jun 08 '18 at 04:34
  • @Locked see the commented return statement I added at the bottom of my function – Olivier Melançon Jun 08 '18 at 04:35
  • This method works for small primes. For the large primes of thousands of bits used in cryptography this method is too slow to be useful. More advanced algorithms are used in that domain. If one must prove primality there are still advanced algorithms that are reasonably fast for large primes, such as elliptic curve primality proving or the more recent AKS-type algorithms. – President James K. Polk Jun 10 '18 at 00:49
0

Try the below code, the speed of it is the same as Olivier Melançon's solution:

from math import sqrt; from itertools import count, islice

def is_prime(n):
    return n > 1 and all(n%i for i in islice(count(2), int(sqrt(n)-1)))

print(is_prime(5))

Output:

True
U11-Forward
  • 41,703
  • 9
  • 50
  • 73