Prime number problem.

I'm trying to create a simple program that tells me if the number entered is a prime number or not. I'm kind of stuck... I think it the problem is more with the math than the actual program itself. This is what I got:

import java.util.*;

publicclass Ch5Prg7

{

static Scanner console =new Scanner(System.in);

publicstaticvoid main (String[]args)

{

int num;

System.out.println("Enter a positive integer.");

num = console.nextInt();

if (num == 1){System.out.println("That number is not prime.");}

if (num == 2){System.out.println("That number is prime.");}

if (num > 2){

// not sure what to do here

}

}

}

Yeah, I know. It's not much. I just don't really know where to begin. Any help with the math or anything in general would be greatly appreciated. :)

[1633 byte] By [JimboPa] at [2007-10-2 4:21:18]
# 1

Well, i don't know if you've found the solution yet but here is what i've done, it couldn't be the most effcient algorithm becuase i'm just high school student:

import java.io.*;

public class FindPrimeNumbers

{

public static void main() throws IOException {

int factor = 0;

BufferedReader input = new BufferedReader (new InputStreamReader(System.in)); //allows input

System.out.print("Please enter a positive interger : ");

int num = Integer.parseInt(input.readLine());

if (num == 1){

System.out.println("That number is not prime.");

}else{

for (int i = 1; i <= num; i++) {

for (int m = 2; m <= num; m++) {

if (m != i) {

if (i % m == 0) { factor = factor + 1; }

}

}

factor = 0;

}

if (factor == 0)

System.out.println(num +" is a prime number");

else

System.out.println(num +" is not a prime number");

}

}

}

A suggestion: When you first time ask for the input you could add some flags in your code to make sure that you're only getting the positive integer, nothing else (e.g. stirng, double, -number etc.).

I hope that helps!!

salubadshaa at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 2

Hi,

After changing main() to main(String[]), I found it told me that

everything except 1 was prime...

The pair of nested loops is more than is needed. Just use a single

loop that looks at each candidate and if it's a factor of num we're

finished. We don't really need to look at everything up to num (for

example we know that 105 isn't a factor 106) - how far should we

search?

Cheers,

Peter

pbrockway2a at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 3
First, I advise you to do some reading in this subject. It can get quite interesting.anyway, you can make sure a number is prime if it doesn't devide in the numbers from 2 to its square root.
TheHattera at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 4

> Hi,

>

> After changing main() to main(String[]), I found it

> told me that

> everything except 1 was prime...

why that affect though? I don't understand?

I don't think that's reason, the whole algorithm is wrong. The program tells you that every number except 1 is prime because i'm reseting the valve of factor back to zero at the end of the loop.

for (int i = 1; i <= num; i++) {

for (int m = 2; m <= num; m++) {

if (m != i) {

if (i % m == 0) { factor = factor + 1; }

}

}

[b]factor = 0;[/b]

}

>

> The pair of nested loops is more than is needed.

> Just use a single

> loop that looks at each candidate and if it's a

> factor of num we're

> finished. We don't really need to look at everything

> up to num (for

> example we know that 105 isn't a factor 106) - how

> far should we

> search?

ok i understand what you're trying to say but what will be the end condition of the loop. Here is something i came up after reading your reply:

salubadshaa at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 5

public static void main(String args[]) throws IOException {

int factor = 0;

BufferedReader input = new BufferedReader (new InputStreamReader(System.in)); //allows input

System.out.print("Please enter a positive interger : ");

int num = Integer.parseInt(input.readLine());

if (num == 1){

System.out.println("That number is not prime.");

}else{

for (int i = 1; i <?; i++) {

factor = 0;

if (num % i == 0) {

factor ++;

}

}

if (factor == 0)

System.out.println(num +" is a prime number");

else

System.out.println(num +" is not a prime number");

}

}

salubadshaa at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 6

i believe the most efficient algorithm is to check every number less than or equal to the number in question, starting at 2. that is, for the number 9, try numbers up to 3 starting at 2. this could be implemented as following:

boolean isPrime = false;

if( num > 1 ) {//if this block is skipped, isPrime == false

int root = Math.sqrt( num );//store result to avoid calling every time through loop (every iteration)

for( int divisor = 2; divisor <= root; divisor++ ) {

if( num % divisor == 0 ) {

isPrime = false;//number is NOT prime

break; //no need to continue loop

}

}

}

if( isPrime ) {

System.out.println("That number is prime.");

}

else {

System.out.println("That number is not prime.");

}

Another algorithm you could use, although it may be slower due to the allocation of the array would be:

boolean isPrime = false;

if( num > 1 ) {//if this block is skipped, isPrime == false

int root = (int)Math.sqrt( num );//store result to avoid calling every time through loop (every iteration)

bool[] possibleFactors = new int[ root + 1 ];

//all array elements are initialized to false by the Java VM

//false indicates untested value, true indicates tested value

for( int divisor = 2; divisor <= root; divisor++ ) {

if( possibleFactors[ divisor ] == false ) {

if( num % divisor == 0 ) {

isPrime = false;//number is NOT prime

break;//no need to continue loop

}

else {

//set all multiples of divisor to true (indicating they were tested) since

//none of the multiples will divide evenly if one of there factors didn't

for( int i = divisor; i <= root; i += divisor ) {

possibleFactors[ i ] = true;

}

}

}

}

}

if( isPrime ) {

System.out.println("That number is prime.");

}

else {

System.out.println("That number is not prime.");

}

@modia at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 7

Generally you want to use subroutines to modularize your code:

Here is a simple prime routine - just one case after another:

public static boolean prime(int p){

if(p<2) return false; // negatives and 1 are not prime

if(p==2) return true; // 2 is prime

if(p%2==0)return false; // all other evens are not prime

for(int i=3; i*i<=p; i+=2) {if(p%i==0) return false;} // if odd p has odd factor it is not prime

return true; // otherwise it is odd and has no factors so is prime.

}

then you can use this routine in your main routine to print out the desired output

System.out.println(m+ " is" + prime(m)?" ":" not" + "prime.");

marlin314a at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 8

salubadsha: yes factor=0 is a bad idea. Why count the factors

anyway?

@modi's (reply 6) first algorithm is what I had in mind. Although

I think it should start isPrime=true. Am I the only one

compiling/running this stuff?

salubadsha: observe how the loop starts at 2, not 1.

We could still do better though. The loop increment

part (divisor++) means we are checking *everything* up

to root. But once we have found that 2 isn't a factor,

why bother checking 4, 6, 8 etc?

Whoops! I've just noticed marlin321 has been there! Maybe

calculating the square root (as an int) is more efficient

than squaring the candidate factor each time. Just a thought

though: can we do better than divisor+=2, given enough special

cases at the start?

Cheers,

Peter

pbrockway2a at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 9

> salubadsha: yes factor=0 is a bad idea. Why count

> the factors

> anyway?

>

> @modi's (reply 6) first algorithm is what I had in

> mind. Although

> I think it should start isPrime=true. Am I the only

> one

> compiling/running this stuff?

>

> salubadsha: observe how the loop starts at 2, not 1.

>

> We could still do better though. The loop increment

> part (divisor++) means we are checking *everything*

> up

> to root. But once we have found that 2 isn't a

> factor,

> why bother checking 4, 6, 8 etc?

>

> Whoops! I've just noticed marlin321 has been there!

> Maybe

> calculating the square root (as an int) is more

> efficient

> than squaring the candidate factor each time. Just a

> thought

> though: can we do better than divisor+=2, given

> enough special

> cases at the start?

>

> Cheers,

>

> Peter

Thanks guys that was really helpful. I was trying to help the other guy but i learned a lot from you both (Peter & @modi). I'm pretty sure in future i won't have any problems with this sort of algorithm.

Regards,

M.salman

salubadshaa at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 10
Is it mathematically proved that every divisor of a number greater than its square root is a product of prime factors we already checked?R. Hollenstein
robinhollensteina at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 11

Hi Robin,

> Is it mathematically proved that every divisor of a

> number greater than its square root is a product of

> prime factors we already checked?

No. It's not true either.

For instance 17 is a divisor of 136 and is bigger than

11-and-a-bit, but it's not a product of *any* (smaller)

primes. Of course if we were checking 136 for primeness

we would have stopped before we got to 17.

The point is that factors come in pairs:

2x68

4x34

8x17

The first is always less than the square root, the second

always greater. It *is* quite easy to prove that every

factor greater than the square root has a partner which

is less than the square root. (Consider what would happen

if the factor and its partner were both greater...) And that's

why the loop only has to go as far as the square root.

Cheers,

Peter

pbrockway2a at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 12

>@modi's (reply 6) first algorithm is what I had in mind. Although

>I think it should start isPrime=true. Am I the only one

>compiling/running this stuff?

sorry, isPrime should start as true. that was a careless error on my part.

this is what the correct code should look like:

boolean isPrime = true;

if( num > 1 ) {//if this block is skipped, isPrime == false

int root = Math.sqrt( num );//store result to avoid calling every time through loop (every iteration)

for( int divisor = 2; divisor <= root; divisor++ ) {

if( num % divisor == 0 ) {

isPrime = false;//number is NOT prime

break; //no need to continue loop

}

}

}

if( isPrime ) {

System.out.println("That number is prime.");

}

else {

System.out.println("That number is not prime.");

}

The second algorithm above (in my first post) tests the minimum amount of factors necessary to determine whether or not the number is prime, since it eliminates multiples of already tested numbers. That might not be the best algorithm, however, due to the overhead of allocating the array, and the overhead of travering it after every new factor is tested. It does provide the advantage on certain iterations of only having to test an array variable, as opposed to testing the factor every time, but this advantage is almost certainly negated by the first two disadvantages (especially since the array has to be allocated dynamically).

@modia at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 13

Here is the fastest prime number tester that doesn't allocate an array:

// very simple prime number test

private static boolean isPrime(int number) {

if (number < 2) return false;

if (number == 2) return true;

if (number % 2 == 0) return false;

if (number == 3) return true;

if (number % 3 == 0) return false;

int y = 2;

int x = (int) Math.sqrt(number);

for (int i = 5; i <= x; i += y, y = 6 - y) {

if (number % i == 0)

return false;

}

return true;

}

rkippena at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 14
Yeah, I just cache a list of primes I already found and just loop through that list. There are many other established facts about primes that can abbreviate the process. http://www.planetmath.org has alot of good info.
swatdbaa at 2007-7-15 23:47:54 > top of Java-index,Other Topics,Algorithms...
# 15

If the goal of your question is learning, take a look

at the best deterministic method that exists today.

http://www.cse.iitk.ac.in/users/manindra/primality_v6.pdf

However, this is academic results only since there are

statistical algorithms that are a lot faster and the

probability for error is so low that other errors like

bugs and bit errors in the processor are drowning the

risk for error due to the algorithm. See method

isProbablePrime(int) at

http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigInteger.html

parza at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 16

>

> The point is that factors come in pairs:

> 2x68

> 4x34

> 8x17

>

> The first is always less than the square root, the second

> always greater. It *is* quite easy to prove that every

> factor greater than the square root has a partne which

> is less than the square root.

Nitpicking:

Actually the first <= and the second >= the square root.

9 = 3 * 3

BIJ001a at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 17

public boolean isPrime(int n) {

if(n < 2)

throw new IllegalArgumentException("Please be sensible!");

if(n < 4 || n % 2 == 0)

return true;

int i, limit = (int) Math.sqrt(n);

for(i = 3; i < limit; i += 2)

if(n % i == 0)

return true;

return false;

}

AlexLamSLa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 18

and if you are performing prime number determination many times in a row, one can adopt a "progressive" approach:

// isPrime(int) as defined above

private List<Integer> primes = new ArrayList<Integer>();

primes.add(2);

primes.add(3);

private void fillPrimesUpTo(int n) {

for(int i = primes.get(primes.size() - 1) + 2; i <= n; i += 2)

if(isPrime(i))

primes.add(i);

}

public boolean isPrimeFast(int n) {

fillPrimesUpTo((int) Math.sqrt(n));

int i, limit = primes.size();

for(i = 0; i < limit; i++)

if(n % primes.get(i))

return true;

return false;

}

AlexLamSLa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 19

Oops... I made a slip in my argument - in fact you don't rely on isPrime(int) at all!

private List<Integer> primes = new ArrayList<Integer>();

primes.add(2);

primes.add(3);

private int nextN = 5;

private void fillPrimesUpTo(int n) {

if(n < nextN)

return;

for(int i = nextN; i <= n; i += 2)

if(isPrimeFast(i))

primes.add(i);

nextN = primes.get(primes.size() - 1) + 2;

}

public boolean isPrimeFast(int n) {

fillPrimesUpTo((int) Math.sqrt(n));

int i, limit = primes.size();

for(i = 0; i < limit; i++)

if(n % primes.get(i))

return true;

return false;

}

AlexLamSLa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 20

Nice try, but no cigar!

I wrote a main routine to test your code and gave it a more appropriate name. Observe the output.

public static boolean bogusIsPrime(int n) {

if(n < 2)

throw new IllegalArgumentException("Please be sensible!");

if(n < 4 || n % 2 == 0)

return true;

int i, limit = (int) Math.sqrt(n);

for(i = 3; i < limit; i += 2)

if(n % i == 0)

return true;

return false;

}

public static void main(String args[]){

System.out.println("Starting");

for(int i = 2; i<20; i++){

System.out.println(i + " - isPrime = " + bogusIsPrime(i));

}

System.out.println("Stoping");

}

Output:

Starting

2 - isPrime = true

3 - isPrime = true

4 - isPrime = true

5 - isPrime = false

6 - isPrime = true

7 - isPrime = false

8 - isPrime = true

9 - isPrime = false

10 - isPrime = true

11 - isPrime = false

12 - isPrime = true

13 - isPrime = false

14 - isPrime = true

15 - isPrime = false

16 - isPrime = true

17 - isPrime = false

18 - isPrime = true

19 - isPrime = false

Stoping

I especially like the result for 15. You'll see why if you fix all the obvious errors.

marlin314a at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 21

well that's easy to fix, I guess:

public boolean isPrime(int n) {

if(n < 2)

throw new IllegalArgumentException("Please be sensible!");

if(n < 4 || n % 2 == 0)

return true;

int i, limit = (int) Math.sqrt(n);

for(i = 3; i <= limit; i += 2)

if(n % i == 0)

return false;

return true;

}

AlexLamSLa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 22

> well that's easy to fix, I guess:

Since the OP now has seen almost every solution (incorrect, correct, slow, fast etc.), here's one more:

public boolean isPrimeTheLazyWay(int i) {

if(i < 0) return false;

return (new java.math.BigInteger(Integer.toString(i))).isProbablePrime(100);

}

prometheuzza at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 23
true - I used this myself for my crypto project last year.
AlexLamSLa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 24

Like JimBo, I'm also having a problem with finding prime numbers. It keeps giving me the error message (PrimalityTester.java:46: missing return statement) right by my primetest method. I'm new to java, so you will notice that the code is simplistic. I would appreciate any suggestions or comments on my coding. We were required to put this in an applet, use the JTextArea with a scroller:

// import java packages

import javax.swing.*;

import java.awt.Container;

public class PrimalityTester extends JApplet

{

public void init()

{

// JTextArea to display prime numbers

JTextArea printPrime = new JTextArea();

// get applet's content pane and attach JTextArea

Container container = getContentPane();

container.add( printPrime );

// attach JTextArea to a JScrollPane so user can scroll results

JScrollPane scroller = new JScrollPane(printPrime);

// set first and second line of text in printPrime

printPrime.setText( "PRIME NUMBERS\n2" );

// loop to test numbers three through 10,000

for (int counter = 3; counter <=10000; counter++ )

if ( primetest(counter)==true )

// append result to JTextArea if true

printPrime.append( "\n" + counter );

}// end method init

// primetest method to test numbers for primality

public boolean primetest( int number )

{

double root=Math.sqrt(number);

// loop to test even divisibility from 2-squareroot of number

for ( int test=2; test <=root; test++ )

// if statement to test even divisibility

if ( number % test==0 )

return false;

} // end primetest method

} // end class PrimalityTester

Leos-Kata at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 25

Well it seems nice algorithm but needs a fix as follows

...

...

// if (n < 4 || n % 2 == 0)

// return true; replace these lines by the code below

if(n<4) return true;

if(n % 2 == 0) return false;

....

....

goita at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 26
You're not returning true if the number is a prime
DaanSa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...
# 27
> You're not returning true if the number is a primeClarification: this was meant for Leos-Kat
DaanSa at 2007-7-20 18:13:40 > top of Java-index,Other Topics,Algorithms...