3

When I run this code, even for just counting to the 10th prime number (instead of 1000) I get a skewed/jacked output--all "not prime" titles for my is_composite variable, my test_num is giving me prime and composite numbers, and my prime_count is off

Some of the answers that developers have shared use functions and the math import--that's something we haven't yet covered. I am not trying to get the most efficient answer; I am just trying to write workable python code to understand the basics of looping.


  # test a prime by diving number by previous sequence of number(s) (% == 0).  Do this by
  # counting up from 1 all the way to 1000.

test_num = 2 #these are the numbers that are being tested for primality
is_composite = 'not prime' # will be counted by prime_count
prime_count = 0 #count the number of primes


while (prime_count<10): #counts number primes and make sures that loop stops after the 1000th prime (here: I am just running it to the tenth for quick testing)


 test_num = test_num + 1   # starts with two, tested for primality and counted if so
 x = test_num - 1  #denominator for prime equation

 while (x>2):   
  if test_num%(x) == 0:
   is_composite = 'not prime'
  else: 
   prime_count = prime_count + 1 
  x = x - 1 


  print is_composite
  print test_num
  print prime_count 
zkidd
  • 493
  • 1
  • 5
  • 16
  • 2
    What *specifically* is not working? – eldarerathis Oct 07 '10 at 21:17
  • Nothing is returning/happening – zkidd Oct 07 '10 at 21:18
  • 6
    Your algorithm is slow, refine it using number theory. Specifically only check against primes less than or equal to the square root of the current number. – alternative Oct 07 '10 at 21:19
  • 5
    Off topic: some comments in your code are correct, other are obvious: `while x > 2: # runs while x is greater than 2` is self-evident. In general: comment the why, not the what. – Adriano Varoli Piazza Oct 07 '10 at 21:23
  • Thanks Adriano -- I'll keep that in mind from now on re: comments – zkidd Oct 07 '10 at 21:31
  • This is homework. We all know it is exactly the first problem of the first problem set of the first assignment of [Introduction to Computer Science and Programming](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/assignments/) from MIT. – Wok Oct 07 '10 at 21:32
  • I don't see any print statements or other outputs, so nothing is returning or (visibly) happening. – Russell Borogove Oct 07 '10 at 21:34
  • This sounds a lot like projecteuler – ajnatural Oct 07 '10 at 21:35
  • 2
    You and I have different ideas for *"big"* prime numbers. To me, a large prime number is large enough that all primes less than that candidate prime number would occupy more memory (hard drive space?) than is available on the machine (cluster?) testing the candidate prime for primality. To me, the first approximately 2^40 primes are *small* – SingleNegationElimination Oct 07 '10 at 22:28
  • I was the one who retitled the question using 'big'. – Adriano Varoli Piazza Oct 07 '10 at 22:53
  • DGM - this is homework -- but for OpenCourse Ware -- no grade. Just trying to learn. – zkidd Oct 08 '10 at 01:49
  • 2
    @zkidd: the problem is not with the cause of homework, but with your approach: if you had come with this question and said "I've done this and that, and I have this problem here" it would show that you were genuinely stumped after making effort. Coming and saying "I have trouble" with some code that, at first, didn't even have a print statement, shows lack of effort. – Adriano Varoli Piazza Oct 08 '10 at 12:37
  • Try this http://unreachable2027.wordpress.com/2012/10/02/python-script-to-find-nth-prime-optimized/ – goutham2027 Feb 02 '14 at 05:57

4 Answers4

3

See the hints given by MIT for your assignment. I quote them below:

  1. Initialize some state variables

  2. Generate all (odd) integers > 1 as candidates to be prime

  3. For each candidate integer, test whether it is prime

    3.1. One easy way to do this is to test whether any other integer > 1 evenly divides the candidate with 0 remainder. To do this, you can use modular arithmetic, for example, the expression a%b returns the remainder after dividing the integer a by the integer b.

    3.2. You might think about which integers you need to check as divisors – certainly you don’t need to go beyond the candidate you are checking, but how much sooner can you stop checking?

  4. If the candidate is prime, print out some information so you know where you are in the computation, and update the state variables

  5. Stop when you reach some appropriate end condition. In formulating this condition, don’t forget that your program did not generate the first prime (2).

It could look like this:

def primes(n):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)/(2*i)+1)
    return [2] + [i for i in xrange(3,n,2) if sieve[i]]
Wok
  • 4,468
  • 5
  • 34
  • 56
  • yesterday I went through those hints, but still am having issues. hence my post. – zkidd Oct 07 '10 at 21:45
  • Feeling pretty bad that I am asking this question even though I went through those hints and re-watched the lecture too. – zkidd Oct 07 '10 at 21:46
  • 1
    You may want to have a look at [more efficient solutions](http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/) to get the Pythonic way. – Wok Oct 07 '10 at 21:49
1

First of all, from the vague description of your prime checking algorithm, it appears that you are checking every number up to the number that you are testing for primality. However, in reality you are only required to test up to the square root of that number. A further optimization would be to remove all even numbers apart from two (you can do this by incrementing by twos from one and testing 2 separately), you end up with:

def isprime(test):
    if test == 2: return True
    if test < 2 or test % 2 == 0: return False
    return not any(test % i == 0 for i in range(3, int(sqrt(test)) + 1, 2))

Then all you have to do is iterate through the numbers from 2 upwards checking if they are prime and adding one to your counter if they are. When you reach 1000 stop and output the number being passed to the isprime function.

Of course there are other more efficient methods, I personally prefer the Sieve of Atkin. But it would be up to you to implement that, my algorithm will serve your purposes.

Edit: I noticed your comment that 'nothing is returning/happening' that would be due to the inefficiency of your algorithm, if you wait long enough you will get an answer. However, I do notice that you have no print statement in the code you provided, I'm hoping the code which your running has one.

from math import sqrt

def isprime(test):
    if test == 2: return True
    if test < 2 or test % 2 == 0: return False
    return not any(test % i == 0 for i in range(3, int(sqrt(test)) + 1, 2))

test_num = 2
prime_count = 1

while (prime_count< 1000): 

 test_num = test_num + 1  

 if (isprime(test_num)):
     prime_count += 1

print test_num
ajnatural
  • 783
  • 9
  • 28
  • You don't need to write a separate `isprime` function. You can check the previous prime integers found as divisors for the current one, since you make an increasing sequence. – Wok Oct 07 '10 at 21:43
  • Have a look at [`rwh_primes(n)`](http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188) for instance. – Wok Oct 07 '10 at 21:56
  • Mine is simply an alternative algorithm, it achieves the same result less efficiently. I provided the alternative Sieve of Atkin if zkidd wanted to look into it. – ajnatural Oct 07 '10 at 21:57
  • Thnx wok and njak32--I'm going to look at everything. But now I am running the program it looks like it's going to "49" and stopping. I added in the print statement I am using. But the prime count does go up to 1000. Can either of you check to see if the above is right? – zkidd Oct 07 '10 at 22:02
  • Begin prime_count at 1, as you aren't counting 2 in your current method. – ajnatural Oct 07 '10 at 22:10
  • Thanks njak32! Your answer uses the math.import and the def --- we haven't covered that, but I'll use your output to check my (less efficient) output – zkidd Oct 07 '10 at 22:21
0

This is a code I wrote for C++. But the mentality must be the same.

// This code was written by Mert Ener
#include <time.h>
#include <vector>
#include <iostream>

private: System::Void button1_Click_1(System::Object^  sender, 
                                          System::EventArgs^  e) { 
    using namespace std;
    UInt64 cloc = clock();
    long m = 1;
    long k = long::Parse(textBox1->Text)-2;   // The text you entered 
    std::vector<long> p(1,2);                 //   for the nth prime
    for( long n = 0; n <= k; n++ ) {
        m += 2;
        for( long l = 1; l <= n; l++ ) {
            if (m % p[l] == 0) {
                m += 2;
                l=0;}}
        p.push_back(m);}
    textBox2->Text = p[k+1].ToString(); // The textbox for the result.
    MessageBox::Show("It took me " + (clock() - cloc).ToString() 
                     + " milliseconds to find your prime.");}
Will Ness
  • 62,652
  • 8
  • 86
  • 167
Flashbond
  • 13
  • 1
  • 1
  • 6
-1

This code below generates a list of primes upto 1 million. Using that list, you can test for primes < 1 Trillion in a reasonably fast way. This runs in a pretty fast time for 10-12 digit primes.

import math
from itertools import islice
# number of primes below the square root of x
# works well when x is large (x > 20 and much larger)
numchecks = lambda x: int((math.sqrt(x))/(math.log(math.sqrt(x)) - 1.084)) + 1

primes = [2,3,5]
primes = primes + [x for x in range(7, 48, 2) if all((x%y for y in islice( primes, 1, int(math.sqrt(x)) )))]
primes = primes + [x for x in range(49, 2400, 2) if all((x%y for y in islice( primes, 1, numchecks(x) )))]
primes = primes + [x for x in range(2401, 1000000, 2) if all((x%y for y in islice( primes, 1, numchecks(x) )))]

You can increase the number of saved primes by extending the process above, but the program will take a long time (but one time only process).

In your code, you can test if 'test_num' is prime using the following...

test_num = 23527631
if test_num<100:
    checks = int(math.sqrt(test_num))
else:
    checks = numchecks(test_num)

isPrime = all(test_num%x for x in islice(primes, 0, checks))
print 'The number is', 'prime' if isPrime else 'not prime'
print 'Tested in', checks, 'divisions'
Rajan
  • 893
  • 1
  • 7
  • 14