10
count = 0
i = 11

while count <= 1000 and i <= 10000:
    if i%2 != 0:
       if (i%3 == 0 or i%4 == 0 or i%5 == 0 or i%6 == 0 or i%7 == 0 or i%9 == 0):
           continue
       else:
           print i,'is prime.'
           count += 1
    i+=1

I'm trying to generate the 1000th prime number only through the use of loops. I generate the primes correctly but the last prime i get is not the 1000th prime. How can i modify my code to do so. Thank in advance for the help.

EDIT: I understand how to do this problem now. But can someone please explain why the following code does not work ? This is the code I wrote before I posted the second one on here.

count = 1
i = 3
while count != 1000:
    if i%2 != 0:
       for k in range(2,i):
          if i%k == 0:
            print(i)
            count += 1
            break
     i += 1
Santosh Kumar
  • 22,275
  • 18
  • 59
  • 100
Amber Roxanna
  • 1,529
  • 4
  • 21
  • 28
  • 9
    What is a prime number? – Blender Mar 14 '13 at 02:29
  • 3
    The current code is flawed - imagine a number divisible by 11, but not 3, 4 (?? - 2 * 2), 5, 6 (?? - 2 * 3), 7, or 9 (?? - 3 * 3). –  Mar 14 '13 at 02:29
  • 2
    In addition to the other flaws, you start with i = 11, so even if you did generate primes correctly, the last prime you generate wouldn't be the 1000th but the 1000th after 11 – Kyle Heuton Mar 14 '13 at 02:30
  • 1
    Hint: Your `if` should check divisibility by all the primes below the square root of number... Hint 2: You don't do that by putting them all in a single `if` statement... Hint 3: `4` is divisible by `2` already – JBernardo Mar 14 '13 at 02:32
  • 1
    I've found that when needing such a trivially small number of primes, the best solution is to not write code at all :P [List of first 1000 primes](http://primes.utm.edu/lists/small/1000.txt) – Edgar Allan Pwn Mar 14 '13 at 03:04
  • Instead of your big long if, you can write this: `if any(i%x for x in range(i**0.5)):` – John La Rooy Mar 14 '13 at 03:07
  • 2
    Consider using `i += 2` then you don't need to do the `if i%2 != 0:` test – John La Rooy Mar 14 '13 at 03:08
  • http://unreachable2027.wordpress.com/2012/10/02/python-script-to-find-nth-prime-optimized/ – goutham2027 Jul 14 '14 at 15:46

13 Answers13

9

Let's see.

count = 1
i = 3
while count != 1000:
    if i%2 != 0:
       for k in range(2,i):
          if i%k == 0:        # 'i' is _not_ a prime!
            print(i)       # ??
            count += 1     # ??
            break
     i += 1          # should be one space to the left,
                     # for proper indentation

If i%k==0, then i is not a prime. If we detect that it's not a prime, we should (a) not print it out, (b) not increment the counter of found primes and (c) we indeed should break out from the for loop - no need to test any more numbers.

Also, instead of testing i%2, we can just increment by 2, starting from 3 - they will all be odd then, by construction.

So, we now have

count = 1
i = 3
while count != 1000:
    for k in range(2,i):
        if i%k == 0:       
            break
    else:
        print(i)
        count += 1
    i += 2        

The else after for gets executed if the for loop was not broken out of prematurely.

It works, but it works too hard, so is much slower than necessary. It tests a number by all the numbers below it, but it's enough to test it just up to its square root. Why? Because if a number n == p*q, with p and q between 1 and n, then at least one of p or q will be not greater than the square root of n: if they both were greater, their product would be greater than n.

So the improved code is:

from math import sqrt

count = 1
i = 1
while count < 1000:
    i += 2
    for k in range(2, 1+int(sqrt(i+1))):
        if i%k == 0:       
            break
    else:
        # print(i) ,
        count += 1
        # if count%20==0: print ""
print i

Just try running it with range(2,i) (as in the previous code), and see how slow it gets. For 1000 primes it takes 1.16 secs, and for 2000 – 4.89 secs (3000 – 12.15 ses). But with the sqrt it takes just 0.21 secs to produce 3000 primes, 0.84 secs for 10,000 and 2.44 secs for 20,000 (orders of growth of ~ n2.1...2.2 vs. ~ n1.5).

The algorithm used above is known as trial division. There's one more improvement needed to make it an optimal trial division, i.e. testing by primes only. An example can be seen here, which runs about 3x faster, and at better empirical complexity of ~ n1.3.


Then there's the sieve of Eratosthenes, which is quite faster (for 20,000 primes, 12x faster than "improved code" above, and much faster yet after that: its empirical order of growth is ~ n1.1, for producing n primes, measured up to n = 1,000,000 primes):

from math import log

count = 1 ; i = 1 ; D = {}
n = 100000                        # 20k:0.20s 
m = int(n*(log(n)+log(log(n))))   # 100k:1.15s 200k:2.36s-7.8M 
while count < n:                  #            400k:5.26s-8.7M 
        i += 2                    #            800k:11.21-7.8M 
        if i not in D:            #            1mln:13.20-7.8M (n^1.1)
            count += 1
            k = i*i
            if k > m:  break      # break, when all is already marked
            while k <= m:
                D[k] = 0 
                k += 2*i
while count < n:
        i += 2
        if i not in D: count += 1
if i >= m: print "invalid: top value estimate too small",i,m ; error
print i,m  

The truly unbounded, incremental, "sliding" sieve of Eratosthenes is about 1.5x faster yet, in this range as tested here.

Community
  • 1
  • 1
Will Ness
  • 62,652
  • 8
  • 86
  • 167
5

A couple of problems are obvious. First, since you're starting at 11, you've already skipped over the first 5 primes, so count should start at 5.

More importantly, your prime detection algorithm just isn't going to work. You have to keep track of all the primes smaller than i for this kind of simplistic "sieve of Eratosthanes"-like prime detection. For example, your algorithm will think 11 * 13 = 143 is prime, but obviously it isn't.

PGsimple1 here is a correct implementatioin of what the prime detection you're trying to do here, but the other algorithms there are much faster.

MattW
  • 3,940
  • 1
  • 10
  • 10
3

Are you sure you are checking for primes correctly? A typical solution is to have a separate "isPrime" function you know that works.

def isPrime(num):
    i = 0
    for factor in xrange(2, num):
        if num%factor == 0:
            return False
    return True

(There are ways to make the above function more effective, such as only checking odds, and only numbers below the square root, etc.)

Then, to find the n'th prime, count all the primes until you have found it:

def nthPrime(n):
    found = 0
    guess = 1
    while found < n:
        guess = guess + 1
        if isPrime(guess):
            found = found + 1
    return guess
tor
  • 596
  • 3
  • 6
  • 17
2

your logic is not so correct. while :

if i%2 != 0:
    if (i%3 == 0 or i%4 == 0 or i%5 == 0 or i%6 == 0 or i%7 == 0 or i%9 == 0):

this cannot judge if a number is prime or not .

i think you should check if all numbers below sqrt(i) divide i .

zds_cn
  • 248
  • 1
  • 2
  • 9
  • Check all primes below sqrt(i), there's no point in checking non-primes. (if i%4 == 0 or i%6 == 0 then i%2 must == 0) – MattW Mar 14 '13 at 02:36
  • we should use:for i in range(0,sqrt(number))[::2]:if(number%i) it is prime.don't we ? – zds_cn Mar 14 '13 at 02:46
  • I'm not a python guy so I'm not 100% sure of the exact syntax here, but I'm pretty sure that should at least be range(2, sqrt(number)) - number % 1 is always 0, and logically number % 0 isn't defined. – MattW Mar 14 '13 at 02:51
1

Here's a is_prime function I ran across somewhere, probably on SO.

def is_prime(n):
  return all((n%j > 0) for j in xrange(2, n))

primes = []

n = 1
while len(primes) <= 1000: 
    if is_prime(n):
        primes.append(n)
    n += 1

Or if you want it all in the loop, just use the return of the is_prime function.

primes = []    
n = 1
while len(primes) <= 1000: 
    if all((n%j > 0) for j in xrange(2, n)):
        primes.append(n)
    n += 1
monkut
  • 36,357
  • 21
  • 109
  • 140
  • 2
    `while True: if foo: break`.. ouch. If this anti pattern doesn't already have a name it really needs one. – Voo Mar 14 '13 at 02:39
  • Isn't that supposed to be `while len(primes) < 1000`? (the question asks for 1,000 not 10,000); doing the loop-forever-but-breakout form (which isn't really saying what you mean, though it works) you need to break `if len(primes) >= 1000` – MattW Mar 14 '13 at 02:46
  • yeah, I started thinking to increment differently, but didn't go back and fix the while loop structure... thx! – monkut Mar 14 '13 at 03:11
  • That prime function was very interesting. of course at this stage of my programming background, i'm not worried about best running time. – Amber Roxanna Mar 14 '13 at 11:35
0

This is probably faster: try to devide the num from 2 to sqrt(num)+1 instead of range(2,num).

from math import sqrt

i = 2 
count = 1

while True:
    i += 1
    prime = True
    div = 2
    limit = sqrt(i) + 1
    while div < limit:
        if not (i % div):
            prime = False
            break
        else:
            div += 1
    if prime:
        count += 1
    if count == 1000:
        print "The 1000th prime number is %s" %i
        break
0

Try this:

def isprime(num):
    count = num//2 + 1
    while count > 1:
        if num %count == 0:
            return False
        count -= 1
    else:
        return True

num = 0
count = 0
while count < 1000:
    num += 1
    if isprime(num):
        count += 1
    if count == 1000:
        prime = num

Problems with your code:

  1. No need to check if i <= 10000.
  2. You are doing this

    if i%2 != 0:
        if (i%3 == 0 or i%4 == 0 or i%5 == 0 or i%6 == 0 or i%7 == 0 or i%9 == 0):
    

    Here, you are not checking if the number is divisible by a prime number greater than 7. Thus your result: most probably divisible by 11

  3. Because of 2. your algorithm says 17 * 13 * 11 is a prime(which it is not)

pradyunsg
  • 13,385
  • 10
  • 36
  • 80
0

How about this:

#!/usr/bin/python

from math import sqrt

def is_prime(n):
    if n == 2:
        return True
    if (n < 2) or (n % 2 == 0):
        return False
    return all(n % i for i in xrange(3, int(sqrt(n)) + 1, 2))

def which_prime(N):
    n = 2
    p = 1
    while True:
        x = is_prime(n)
        if x:
            if p == N:
                return n
            else:
                p += 1
        n += 1
print which_prime(1000)
James
  • 13,197
  • 8
  • 42
  • 62
0
n=2                         ## the first prime no.
prime=1                     ## we already know 2 is the first prime no.
while prime!=1000:          ## to get 1000th prime no.
    n+=1                    ## increase number by 1
    pon=1                   ## sets prime_or_not(pon) counter to 1
    for i in range(2,n):    ## i varies from 2 to n-1
        if (n%i)==0:        ## if n is divisible by i, n is not prime
            pon+=1          ## increases prime_or_not counter if  n is not prime
    if pon==1:              ## checks if n is prime or not at the end of for loop
        prime+=1            ## if n is prime, increase prime counter by 1
print n                     ## prints the thousandth prime no.
0

Here is yet another submission:

ans = 0;
primeCounter = 0;
while primeCounter < 1000:
    ans += 1;    
    if ans % 2 != 0: 
        # we have an odd number
        # start testing for prime
        divisor = 2;
        isPrime = True;
        while divisor < ans:
            if ans % divisor == 0: 
                isPrime = False;
                break;
            divisor += 1;
        if isPrime:             
            print str(ans) + ' is the ' + str(primeCounter) + ' prime';
            primeCounter += 1;
print 'the 1000th prime is ' + str(ans);
Shaun Luttin
  • 107,550
  • 65
  • 332
  • 414
0

Here's a method using only if & while loops. This will print out only the 1000th prime number. It skips 2. I did this as problem set 1 for MIT's OCW 6.00 course & therefore only includes commands taught up to the second lecture.

prime_counter = 0  
number = 3  

while(prime_counter < 999):
    divisor = 2
    divcounter = 0
    while(divisor < number):
        if(number%divisor == 0):
            divcounter = 1  
        divisor += 1
    if(divcounter == 0):
        prime_counter+=1
    if(prime_counter == 999):
        print '1000th prime number: ', number
    number+=2
kronosjt
  • 393
  • 3
  • 6
  • 21
0

I just wrote this one. It will ask you how many prime number user wants to see, in this case it will be 1000. Feel free to use it :).

# p is the sequence number of prime series
# n is the sequence of natural numbers to be tested if prime or not
# i is the sequence of natural numbers which will be used to devide n for testing
# L is the sequence limit of prime series user wants to see
p=2;n=3
L=int(input('Enter the how many prime numbers you want to see: '))
print ('# 1  prime is 2')
while(p<=L):
    i=2
    while i<n:
        if n%i==0:break
        i+=1
    else:print('#',p,' prime is',n); p+=1
    n+=1 #Line X

#when it breaks it doesn't execute the else and goes to the line 'X' 
0

This will be the optimized code with less number of executions, it can calculate and display 10000 prime numbers within a second. it will display all the prime numbers, if want only nth prime number, just set while condition and print the prime number after you come out of the loop. if you want to check a number is prime or not just assign number to n, and remove while loop.. it uses the prime number property that * if a number is not divisible by the numbers which are less than its square root then it is prime number. * instead of checking till the end(Means 1000 iteration to figure out 1000 is prime or not) we can end the loop within 35 iterations, * break the loop if it is divided by any number at the beginning(if it is even loop will break on first iteration, if it is divisible by 3 then 2 iteration) so we iterate till the end only for the prime numbers

remember one thing you can still optimize the iterations by using the property *if a number is not divisible with the prime numbers less than that then it is prime number but the code will be too large, we have to keep track of the calculated prime numbers, also it is difficult to find a particular number is a prime or not, so this will be the Best logic or code

import math
number=1
count = 0

while(count<10000):
    isprime=1
    number+=1
    for j in range(2,int(math.sqrt(number))+1):
        if(number%j==0):
            isprime=0   
            break
    if(isprime==1):
        print(number,end=" ")
        count+=1