I'm in an intro to Java class and just finished an assignment, but I was left with a question in my head. I did not have time to ask my professor yet and it's a bit off topic from what we're doing anyhow.
Basically we had a program that will validate if a user inputted integer is prime or not. If it isn't prime, it calculates the closest prime number smaller than the input. For example:
Enter an integer: 4
4 is not a prime number. The closest prime number is 3.
The program works as intended using a loop if the input is not prime. Here is my code:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int number;
System.out.print("Please enter a positive, non-zero integer: ");
number = input.nextInt();
input.close();
if (isValid(number) == true) {
if(isPrime(number) == true) {
System.out.printf("%d is a prime number.", number);
} else {
switch(number) {
case 1:
System.out.print("1 is not a prime number. \n");
System.out.print("We cannot find the nearest prime.");
break;
default:
System.out.printf("%d is not a prime number.", number);
System.out.printf("\nThe nearest prime number is %d.", getNearestPrime(number));
}
}
} else {
System.out.print("Invalid input. Please run again.");
System.exit(1);
}
}
public static boolean isValid(int number) {
if (number > 0) {
return true;
} else {
return false;
}
}
public static boolean isPrime(int number) {
int i;
if(number == 1) {
return false;
} else {
for(i = 2; i < number; i++) {
if(number%i == 0) {
return false;
}
}
return true;
}
}
public static int getNearestPrime(int number) {
do {
number--;
} while (isPrime(number) == false);
return number;
}
It's important to note we were required to create the three methods listed below main.
My question is this: is there a way to increase performance when calculating larger ints in this scenario?
If I was to input 2,147,483,647, the program takes about 10 seconds to recognize it's prime. If I enter 2,147,483,646, it takes roughly the same time to find the closest prime.
I completely understand why this happens, but it seems like any high level Java applications I've used can computer way more complex things much faster than my simple program can.
I'm genuinely just curious how experienced programmers handle something like this. Thank you!
Several simple things you can change:
1) A prime number will never be even, so once you check if a number is divisible by two, you don't need to check if it is divisible by any other even number. So you can simplify your loop a little. (Just add an if statement to check if the number is 2 and then start i at three)
2) You only have to loop until the square root of the number.
int i;
if(number == 1) {
return false;
}
if(number == 2) {
return true; //2 is a prime number
}
if (number % 2 == 0) {
return false;
}
for(i = 3; i* i <= number; i+=2) {
if(number%i == 0) {
return false;
}
}
return true;
Well one thing to note is that algorithmic wise there are more efficient algorithms to use. See this answer for details
Regarding implementation you can for example employ some tricks such as caching of recent results if you want to increase performance.
A more efficient approach but perhaps outside the scope of a course would be to use a list of precalculated primes.
You can find one in the internet or you can run a program once to precalculate them up to a given point.
Do note that this approach would trade off some memory for the sake of speed.
Related
This Code works properly for numbers upto 4 but then prints wrong or sometimes both, "Number is Prime" and "not Prime".
package timepass;
import java.util.Scanner;
public class Timepass {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter the no :");
int n = sc.nextInt();
if (n==1 || n==0) {
System.out.println("It is not a prime no");
}
else if (n > 1) {
for(int i = 2; i<n; i++) {
if (n % i ==0) {
System.out.println("It is not a prime number");
break;
} else {
System.out.println("It is a prime number");
}
}
}
}
}
There is slight mistake in the logic.
You have to check all the integers from 2 to n-1, if they are factors of n and then make the final verdict.
Have a look at the following implementation:
import java.util.Scanner;
public class Timepass {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter the no :");
int n = sc.nextInt();
if (n==1 || n==0) {
System.out.println("It is not a prime no");
}
else if (n > 1) {
boolean isPrime = true;
for(int i = 2; i<n; i++) {
if (n % i ==0) {
isPrime = false;
break;
}
}
if(isPrime) {
System.out.println("It is a prime number");
}else{
System.out.println("It is not a prime number");
}
}
}
}
PS: Also search for more efficient logics to check if the number is prime. For example: In the above code, their is no need to iterate from 2 until n-1. You can stop at n/2.
I see the problem.
Hint: a number is prime if there are no factors. Your code is printing "prime" when >>a<< number is not a factor.
Look at the example 5 and your loop.
2: not a factor, print "It is a prime number"
3: not a factor, print "It is a prime number"
4: not a factor, print "It is a prime number"
When can you as a human tell that it is a prime number? Surely not already at 2.
(Actually you can at 3, but your loop condition is inefficient....)
So why do you print already? You should not.
Look at 9:
2: not a factor, print "It is a prime number"
3: is a factor, print "It is not a prime number"; break, stop looping
Again, at 2 you do not know yet but print anyway; at three you know and stop.
The solution is to print in all cases only when leaving the loop. You do so correctly before the break for "not prime". But you print several times for "prime", possibly wrongly and possibly later again for "not prime".
The point to print "prime" is after going through all of the loop without finding a factor.
Make sure that you do not do that printing after leaving the loop with break for "not prime". You can do so by introducing a function which does the prime check and returns a value indicating the result. That function can return where you currently break and after the loop. Then print the result text from the calling code, based on the return value.
You should be using a flag variable in order to check the number whether it is prime or not. The problem with your case is that everytime it check if the number is divisible by i and if this condition becomes false then it goes to the else condition and prints 'not prime' and this is wrong the program should wait for the loop to end and then it should print any result.
So use a flag variable, initialize it false and if the number is divisible by any value of i then make the value of flag true and break out of loop.
After the loop check for flag variable and if the variable is true print not prime else prime .
//you can use flag instead of printing the massage inside the for loop
// if flag is true means the number is not a prime number
boolean flag = false;
for(int i =2; i< n; i++){
if(n % i ==0){
flag = true;
break;
}
}
if (flag) {
System.out.println("It is not a prime number");
} else {
System.out.println("It is a prime number");
}
import java.util.Scanner;
class Timepass {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter the no :");
int n = sc.nextInt();
if (n==1 || n==0) {
System.out.println("It is not a prime no");
}
else if (n > 1) {
for(int i = 2; i<n; i++) {
if (n % i ==0) {
System.out.println("It is not a prime number");
break;
} else {
System.out.println("It is a prime number");
break;
}
}
}
}
}
Our Professor gave us a bunch of problems to program. I'm almost done until I read that my last assignment to program, we can't use Boolean and "for". What can I use aside from "for" and "Boolean" to determine if the number is Prime or Not? I hope someone will notice this. Help me, please. Thank you in advance.
A way to solve it without for is by using recursion. If the use of conditionals does not count as a boolean use I think this is an answer to the exercise:
public String verify(int num) {
if (num <= 1) {
return IS_NOT_PRIME;
}
if (num )
return isPrime(num, num);
}
}
public String isPrime(int i, int num) {
if (i == 1) {
return IS_PRIME;
}
if (num % i == 0 && i != num) {
return IS_NOT_PRIME;
}
return isPrime(i-1, num);
}
edit: English, lint and negative numbers fix. Pointed out by Tommy.
You could use a while loop instead of a for-loop, like this:
public class Prime{
static int i = 2;
public static String prime(int n){
if(n <= 0){
return("Please enter a number greater than 0");
}
while(i < n){
if(n % i == 0){
return(n + " is not prime");
}
i++;
}
return (n + " is prime");
}
}
Whenever you have to check any possibility the response is always in form of boolean.
If he is very specific about return data type not being boolean then you can return int (1 or 0).
Alternatives to for loop are while, do-while or recursion.
Alternative to iterative structures is recursion.
Here is the program of checking prime number without using boolean and for loop:
public class PrimeNumber {
public static void main(String args[]) {
PrimeNumber primeNumber = new PrimeNumber();
int i = 2;
int num = 3;
if (num <= 1) {
System.out.println(num + " is not a prime number");
System.exit(1);
}
while(i <= Math.sqrt(num)) {
if (num % i == 0) {
System.out.println(num + " is not a prime number");
System.exit(1);
}
i++;
}
System.out.println(num + " is a prime number");
} }
I have started out recently, this site has helped me once and I'm hoping it helps me again.
I know I have to connect else to if but I don't know how, here is my code,
import java.util.Scanner;
public class even {
public static void main(String[] args) {
System.out.println("Enter a number.");
Scanner scan = new Scanner(System.in);
int n;
n = scan.nextInt();
boolean even;
even = n % 2 == 0;
if (even = true) {
System.out.println("Your number number is even");
else
System.out.println("Your number is odd");
}
}
}
and i am very sorry if this question is off topic but i am new and learning, please don't dislike it and suggest what to do next time
Close the brace, something like
if (even) { // even = true is not good. even == true would work. but if (even)
// is shorter.
System.out.println("Your number number is even");
} else {
System.out.println("Your number is odd");
}
When you say if (even = true) you are assigning true to even which also evaluates to true.
if (even == true) { //can be also written as if (even)
System.out.println("Your number number is even");
} else { //we enter the next block only when `even` is not true
System.out.println("Your number is odd");
}
More details about the if statement, here.
If/Else statements are knitted together by use of curly braces to control the flow of your code and logic. Your if-statement should be altered to:
if (even) {//even is true
System.out.println("Your number number is even");
} else {
System.out.println("Your number is odd");
}
I'm trying to create a program that reads a list of 10 integers and asks the user whether they'd like to know if the integers entered are even/odd, prime, or their sign.
I don't see where the mistake is:
import java.io.*;
public class Menu1 {
public static void main(String args[])throws IOException{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int array[]=new int[10];
int a=0, i=0;
System.out.println("Welcome, please enter 10 integers:");
try{
for(i=0;i<10;i++){
System.out.println("Enter integer "+(i+1)+":");
array[i]=Integer.parseInt(b.readLine());
}
}catch(NumberFormatException e){
System.err.println("Not an integer! "+e.getMessage());
}
System.out.println("What would you like to know?\n(1) Even/Odd\n(2) Primes\n(3) Sign");
try{
a=Integer.parseInt(b.readLine());
}catch(NumberFormatException e){
System.err.println("Not an integer! "+e.getMessage());
}
switch (a){
case 1:
for(i=0;i<10;i++){
if(array[i]%2==0)
System.out.println(array[i]+" is even");
else
System.out.println(array[i]+" is odd");
}
break;
case 2:
for(int j=0;j<10;j++){
for(i=2;i<array[j];i++){
if(array[j]%i==0)
System.out.println(array[j]+" isn't prime");
else
System.out.println(array[j]+" is prime");
}
}
break;
case 3:
for(i=0;i<10;i++){
if(array[i]>0)
System.out.println(array[i]+" is positive");
else if(array[i]<0)
System.out.println(array[i]+" is negative");
else
System.out.println(array[i]+" has no sign");
}
break;
default:
System.out.println("Invalid Option");
}
}
}
case 1 and case 3 work just fine, case 2 is where the strange output occurs; any help will be greatly appreciated
In your code for case 2:
case 2:
for(int j=0;j<10;j++){
for(i=2;i<array[j];i++){
if(array[j]%i==0)
System.out.println(array[j]+" isn't prime");
else
System.out.println(array[j]+" is prime");
}
}
break;
you have put a System.out.println() statement that will execute for every iteration of the for loop. So, if a given element in your array, array, is 5, your code will print out whether or not your number is divisible by every number from 2 to 5. This probably isn't what you want.
To fix this, there are a few options: for one, you could have a boolean flag that you set when you discover that the number isn't prime, and then check that and print your results after the inner for loop:
case 2:
for(int j=0;j<10;j++){
boolean isPrime = true; // assume it's prime
for(i=2;i<array[j];i++){
if(array[j]%i==0)
isPrime = false;
break; // get out of the inner for loop early
}
if(isPrime)
System.out.println(array[j]+" is prime");
else
System.out.println(array[j]+" isn't prime");
}
break;
This is a function to check if a number is prime or not:
public static boolean isPrimeNumber(int number) {
if (number == 2 || number == 3) {
return true;
}
if (number % 2 == 0) {
return false;
}
int sqrt = (int) Math.sqrt(number) + 1;
for (int i = 3; i < sqrt; i += 2) {
if (number % i == 0) {
return false;
}
}
return true;
}
You can call this function for every number you want to check.
Your case2 would be like:
case 2:
for(int j=0;j<10;j++){
if(!isPrimeNumber(array[j]))
System.out.println(array[j]+" isn't prime");
else
System.out.println(array[j]+" is prime");
}
break;
For a programming exercise, the answers given will do just fine. If this were a real application, using very large numbers, the algorithm that checks every possible divisor (or even the slight improvements on this) would be very slow.
Although it's possible to test for primality with certainty much more efficiently than this, in practice it's very, very efficient to check that a (very) large number is almost
certainly prime. This is what gets used in cryptographic applications.
For further details, you could look up Miller-Rabin.
If you want an implementation you can use off-the-shelf, then convert your number to a BigInteger and then use BigInteger.isProbablePrime(int certainty) to determine whether it's probably prime. You can make the "probably" very close to certainty and it'll still be extremely efficient.
I have this assignment that I've tried. But when I enter 1 it should not give any output as 1 is > 0 and 1 is not even but I still get output as:
Enter a +ve number
1
You entered 1
I'd asked for a +ve number :)
.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a +ve number");
int number = input.nextInt();
System.out.println("You entered "+number);
if(number > 0)
if(number %2 == 0)
System.out.println("Number"+number+" is even and +ve");
else
System.out.println("I'd asked for a +ve number :)");
}
}
Your else actually belongs to the 2nd if not the 1st if as the indentation shows.
if(cond1)
if(cond2)
else // this else belongs to 2nd if not 1st if.
is same as:
if(cond1) {
if(cond2) {
} else {
}
}
This is because the Java grammar says that an else belongs to the closest unmatched if to which it can possibly belong.
If you want to match the else with first if you need to use parenthesis as:
if(cond1) {
if(cond2) {
}
} else {
}
Check that the code actually follows the logic it ought to - indentation won't help you with flow control, that's what curly brackets {} are for.
That would probably be because your ifs are interpreted like this:
if(number > 0)
if(number %2 == 0)
System.out.println("Number"+number+" is even and +ve");
else
System.out.println("I'd asked for a +ve number :)");
How's the computer supposed to know what you mean? You need to use brackets to make it unambiguous:
if(number > 0) {
if(number %2 == 0) {
System.out.println("Number"+number+" is even and +ve");
}
} else {
System.out.println("I'd asked for a +ve number :)");
}
I get the following output when I enter 1:
Enter a +ve number
1
You entered 1
I'd asked for a +ve number :)
Which is reasonable as you first check
if (number > 0)
which is true for number == 1 and then you check
if (number % 2 == 0)
which is false for number == 1 thus the else branch is taken:
System.out.println("I'd asked for a +ve number :)")
Your code should probably look something like:
Scanner input = new Scanner(System.in);
System.out.println("Enter a +ve number");
int number = input.nextInt();
System.out.println("You entered " + number);
if (number > 0) {
if (number % 2 == 0)
System.out.println("Number" + number + " is even and +ve");
} else {
System.out.println("I'd asked for a +ve number :)");
}
first you should try to debug (using eclipse maybe)
add paranthesis after if(number > 0) statement to wrap inner if statement.
I threw your code into Netbeans and had it auto format it for readability. Is this your intended logic flow? Because this is how the compiler sees your if statements alignment/nesting.
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter a +ve number");
int number = input.nextInt();
System.out.println("You entered " + number);
if (number > 0)
{
if (number % 2 == 0)
{
System.out.println("Number" + number + " is even and +ve");
}
else
{
System.out.println("I'd asked for a +ve number :)");
}
}
}
}
1 %2 == 1 so it's clear that it enters on the else branch
its because your else statement is saying if its not even then say "i asked for a +ve number"
move it out of the if statement like this
if(number > 0)
{
if(number %2 == 0)
{
System.out.println("Number"+number+" is even and +ve");
}
}
else
{
System.out.println("I'd asked for a +ve number :)");
}