I am trying to run this code to print the sum of all the prime numbers less than 2 million. This loop is never ending. Can anyone tell me what is wrong with the code? It see
Here is a complete program of Prime using JOptionPane, i.e. Java GUI
import javax.swing.*;
public class ChkPrime {
public static void main(String[] args) throws NumberFormatException {
String str = JOptionPane.showInputDialog(null, "Enter any number: ","Input...", 3);
try {
int num = Integer.parseInt(str);
if (num == 1)
JOptionPane.showMessageDialog(null, "Your inputed no. " + num + " is not prime.","Error!", 0);
for(int i = 2; i <= Math.sqrt(num); i++) {
if(num % i == 0) {
JOptionPane.showMessageDialog(null, "Your inputed no. " + num + " is not prime.","Error!", 0);
System.exit(0);
}
}
JOptionPane.showMessageDialog(null, "Your inputed no. " + num + " is prime.","Yeh! Got it!", 1);
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Please input numbers...","Error!", 0);
main(null);
}
}
}
static boolean isPrime(int n) {
if (n == 1) return false;
for(int i = 2; i <= n/2; i++)
if(n % i == 0)
return false;
return true;
}
You have a bug in isPrime()
The test should be:
if(n%i == 0) { ...
and you need to start counting at 2
, not 1
, because every number has a remainder of zero when divided by 1
!
Also, no need to go past Math.sqrt(n)
.
You should change it to this:
private static boolean isPrime(long n) {
long max = (long)Math.sqrt(n);
for (long i = 2; i < max; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
FYI, with this change, I tested the program on my PC and it completed in under 1 second, giving the result of 143064094810
A naive isPrime
function must calculate all the primes up to i
(or at least up to sqrt(i)
) each time it runs. Make sure your isPrime function caches its results!
In isPrime
you are only testing division by 2:
private static boolean isPrime(long n) {
boolean result = false;
for(long i=1; i<n/2; i++) {
if(n%2 == 0) {
result = false;
break;
}
else result = true;
}
return result;
}
it should be division by every i
and starting from 2:
for(long i=2; i<n/2; i++) {
if(n%i == 0) {
...
Practically in your current version an odd number n
will keep dividing by 2 up to n/2
instead of stopping much sooner. Consider n = 21. You are dividing by 2 from 1 to 10, instead of dividing by 3 at the 3rd step and exiting.
It not only gives incorrect results, but also takes much longer than needed to reach a return
statement.
Edit: For faster results check out this sieve of Erathostenes method:
public static long sumOfPrimes(int n) {
long sum = 0;
boolean[] sieve = new boolean[n];
for(int i = 2; i < Math.sqrt(n); i++) {
if(!sieve[i]) {
for(int j = i * i; j < n; j += i) {
sieve[j] = true;
}
}
}
for(int i = 2; i < n; i++) {
if(!sieve[i]) {
sum += i;
}
}
return sum;
}
Edit #2: Found some bugs with your new version. Here's the corrected one:
private static boolean isPrime(long n) {
boolean result = false;
if(n == 2 || n == 3) return true;
for (long i = 2; i <= (long) Math.sqrt(n); i++) {
if (n % i == 0) {
result = false;
break;
} else
result = true;
}
System.out.println(n + " " + result);
return result;
}