Since this has been migrated to CodeReview, it makes sense to inspect it from a review perspective.
Others have correctly pointed out that the limit of your iteration is the root of the the number. That will impact the performance.... but what about your actual question: can the code be shorter (rather than faster)?
First, some comments....
- you really should not use
System.exit(...)
. A simple return
would work better in this situation
- You are not closing the Scanner when you are done with it. I know that in this case, working on
System.in
you don't think it's necessary, but, you should get in the habit of doing it. I have seen too many occasions where unclosed-handles create problems.
- the variable names are horrible ....
x
, y
and i
? (Well, i
is OK....).
- in the current version of the code, you are still doing
i++
and not i+=2
. This is because you are starting at 2
. If you start at 3
you can do a clean +=2
.
Math.sqrt(...)
returns a double
. Doing a comparison against double for each loop is something the JIT compiler may be able to optimize, but I would err on the side of caution, and manually cast it outside the loop.
So, putting it together, I would suggest something like:
public static void main(String args[]){
System.out.println("Enter the number:");
try (Scanner scanner=new Scanner(System.in)) {
final long target = scanner.nextLong();
final long limit = (long)Math.sqrt(target);
for(long factor = 2; factor <= limit; factor += factor == 2 ? 1 : 2){
if(target % factor == 0) {
System.out.printf("%d is not a prime\n%d divides by %d", target, target, factor);
return;
}
}
System.out.println(target + " is a prime number.");
}
}
The above code is reasonably well structured, etc.
If I was aiming for raw performance though, and I threw out some of the validation rules, and allowed myself to hack it a bit, I would consider:
private static final long factor(final long target) {
if (target <= 2) {
return 1; // 1 and 2 are 'prime' external call will have to special-case 1 and negative numbers..
}
if ((target & 0x001) == 0) {
return 2; // it's even.
}
final long limit = (long)Math.sqrt(target);
for(long factor = 3; factor <= limit; factor += 2){
if(target % factor == 0) {
return factor;
}
}
return 1;
}
public static void main(String args[]){
System.out.println("Enter the number:");
try (Scanner scanner=new Scanner(System.in)) {
final long target = scanner.nextLong();
final long fac = factor(target);
if(fac > 1) {
System.out.printf("%d is not a prime\n%d divides by %d", target, target, fac);
return;
}
System.out.println(target + " is a prime number.");
}
}
The reason for this is:
- measuring performance with a single call is never going to do anything in Java - you need to call the code enough times to allow the JIT compiler to compile it.
- It is unlikely that the JIT compiler will ever compile the
main
method
- So I extract the 'hard' logic in to a seperate method that the JIT system can compile and isolate.
- I handle the special cases seperately....
- put the user-dialog outside the calculation....