0

I'm new to computer science and programming. I'm taking a free online class in coding, and one of the assignments was to write a program that will generate the 1000th prime number.

FYI, this is in Python 2.5.4

Here is the original code I copied (and edited a little bit) from another thread on this forum:

def isprime(n):

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

def nthprime(n):
    x=[]
    j=2
    while len(x)<n:
        if (isprime(j)) == True:
            x.append(j)
        j =j+1
    return(x[n-1])

print nthprime(1000)

However, I thought I could make the program faster by rewriting the isprime(n) function as follows:

def isprime(n):# First the primality test
    i=1
    if n<2:
        return False
    if (n!=2 and (n/2*2==n)):
        return False
    if n==3:
        return True
    if n==5:
        return True
    else:
        while i <= (n/2+1):
            i+=2
            if n%i==0:
                return False
        else:
              return True  

That way, when it is only checking if n is divisible by odd integers (by this point in the code, we already know n is odd, and therefore not divisible by any even integers).

I thought that rewriting it this way would make the program work twice as fast (since it's only checking half as many numbers), but it seems to be taking the same amount of time, or even slightly longer, than what it was taking before.

Also, is there any way to rewrite the second block of code to get rid of the:

if n==3:
    return True
if n==5:
    return True 

The only reason I included that is because I realized my algorithm was generating "false" for 3 and 5, even though they are prime.

Any help would be appreciated. Thank you.

Michael Geary
  • 26,814
  • 8
  • 56
  • 71
Matt
  • 27
  • 3
  • 3
    nope, the fastest way is by using the sieve of erathostenes. – Jean-François Fabre Jun 27 '17 at 20:37
  • 4
    [Is it though?](https://en.wikipedia.org/wiki/Sieve_of_Atkin) – Alex Alifimoff Jun 27 '17 at 20:38
  • 1
    `n/2*2==n` is an odd-looking way to determine parity (and incorrect in Python3). How about `n%2==0`? – Robᵩ Jun 27 '17 at 20:39
  • 1
    Atkin may be faster, but it's not very good for a simple programming exercise. Eratosthenes is much simpler and very easy to understand. Its main limitation for an exercise like this is that it doesn't give a direct way to compute the _nth_ prime number. Instead, it computes all the prime numbers up to a predetermined maximum value. Of course you can set a very large maximum value and then count the primes after it's done. – Michael Geary Jun 27 '17 at 20:43
  • @Matt Thanks for asking your question and welcome to Stack Overflow – Joe Jun 27 '17 at 20:43
  • @Jean-FrançoisFabre This is not an exact duplicate of either of the linked questions. The first one is specific to the Sieve of Eratosthenes, the second asks how to find all primes below a maximum value. Neither of these is a direct solution for the question asked here: how to find the _nth_ prime. Please re-open as this is a different question. – Michael Geary Jun 27 '17 at 20:54
  • what do you mean re-open as a different question? – Matt Jun 27 '17 at 21:02
  • 1
    @MichaelGeary I only added the first duplicate. Someone else edited and added another duplicate. Is there a way to find the nth prime without computing the n-1 first ones? would be surprising, and would be surprising if there weren't a Q&A about that either. Also note: the title is "Is this the fastest way to generate prime numbers in Python?". Duplicate links answer that very well. – Jean-François Fabre Jun 27 '17 at 21:25
  • also very similar on code review: https://codereview.stackexchange.com/questions/151095/get-nth-prime-number-using-sieve-of-eratosthenes. Oh now you edited the title :) nice. Find me a way to generate the nth prime number _without_ generating the n-1 previous ones and I'll reopen (sorry I had a lot of bad experiences with reopening on request: either 1) the question got dupehammered again by someone else or 2) someone posted a feeble answer copying the existing answers the original SO questions I linked to...) – Jean-François Fabre Jun 27 '17 at 21:30
  • @Matt I was asking to have your question re-opened because the original two "duplicates" were really a different question. Your question is how to generate the _nth_ prime (the 1000th prime in your example). The other questions asked how to generate all the primes below a certain limit, i.e. list all the primes less than 1000. The Sieve of Eratosthenes is a great way to do that, but you have to allocate a sieve array of the size you need. To generate the 1000th prime, how big an array would you need? Ten thousand? A million? You don't know how many primes you have until you fill the sieve. – Michael Geary Jun 27 '17 at 21:48
  • @Jean-FrançoisFabre Thanks for adding that third duplicate link. (Or thanks to whoever added it.) That one actually is a good duplicate; could it be listed first? See my note to Matt for why a sieve is only a partial solution - it's the difference between getting "the first _n_ primes" vs. "all primes less than _n_". If you want to get the first _n_ primes with a sieve you have to guess at how large a sieve to use. I wonder if an expandable sieve would be a good solution? I didn't see that idea suggested in the duplicate answers. – Michael Geary Jun 27 '17 at 21:55
  • Thanks for all the replies. Actually, the specific question I wanted answered was this: Why is the second block of code in my OP (for testing to see if a number is prime) not computing any faster than the first block of code, when the first block is testing all divisors and the second is only testing odd divisors. For big numbers, shouldn't it run twice as fast? – Matt Jun 28 '17 at 00:18
  • @MichaelGeary it was me, yes :) I made it the first duplicate link as you requested. – Jean-François Fabre Jun 28 '17 at 07:33
  • @Matt: you should take a look at the non-sieve answers. The classical mistake is to loop to `n/2`, whereas you only have to loop to `sqrt(n)` (included) because you would have found any divisors then if there were some. For the 3 and 5 that sounds strange. Look at all the links and check on codereview too (maybe your question is a duplicate of a codereview question too) – Jean-François Fabre Jun 28 '17 at 07:34

0 Answers0