Making my prime/perfect/composite number checker more efficient/cleaner - java

This program asks the user for a minimum number greater than 1 and a maximum number grater than the min. It then prints out number by number what its divisible by, if its prime or composite, and if its a perfect number in this format:
2 is divisible by 1
2 is prime.
2 is not perfect
3 is divisible by 1
3 is prime.
3 is not perfect
4 is divisible by 1 2
4 is composite.
4 is not perfect.
5 is divisible by 1
5 is prime.
5 is not perfect
6 is divisible by 1 2 3
6 is composite.
6 is perfect.
At the end it displays the number of prime and perfect numbers. The program works but I am wondering if there are any ways to clean up the code/make it more efficient(or if there is anything im doing wrong)
Code:
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int min;
int max;
//declaring min and max values
System.out.println("Enter minimum value to check (an integer greater than 1:)");
min=input.nextInt();
while(!(min>1)) {
System.out.println("The entry is valid. Please be sure to enter an integer greater than 1");
System.out.println();
System.out.println("Enter minimum value to check (an integer greater than 1:)");
min=input.nextInt();
}
System.out.println("Enter maximum value to check (an integer greater than your min value:)");
max=input.nextInt();
while(!(max>min)) {
System.out.println("The entry is valid. Please be sure to enter an integer greater than the min value");
System.out.println();
System.out.println("Enter maximum value to check (an integer greater than min:)");
max=input.nextInt();
}
//declaring count and tracking variables
int count;
int numPrime=0;
int numPerfect=0;
int temp=1;
String result=" ";
boolean isPrime=true;
boolean isPerfect=false;
int i;
//main loop
for(count=min;count<=max;count++) {
for(i=2;i<=count;i++) {
if(count%i==0&&i!=count) {
isPrime=false;
result=result+i+" ";
temp+=i;
}
else
isPrime=true;
}
//Perfect counter
if(temp==count) {
isPerfect=true;
numPerfect=numPerfect+1;
}
else
isPerfect=false;
//Composite print
if(!(result.equals(" "))) {
System.out.println(count+" is divisible by 1"+result);
System.out.println(count+" is composite.");
if(isPerfect==true)
System.out.println(count+" is perfect.");
else
System.out.println(count+ " is not perfect.");
System.out.println();
}
//Prime print
else {
numPrime=numPrime+1;
System.out.println(count+" is divisible by 1");
System.out.println(count+" is prime.");
System.out.println(count+" is not perfect");
System.out.println();
}
//reset values
result=" ";
temp=1;
}
System.out.println("Primes found: "+numPrime);
System.out.println("Perfect numbers found: "+numPerfect);
}
}

I have a hobby of making my python perfect number code as efficient as possible so I know a few extra efficiency things but unfortunately I don't code Java so these will just be some generic efficiency improvements.
Firstly, as has been hinted in the comments you only have to check to the square root of the number to get all the divisors but what you do have to do is then add the number / your divisors to your list of divisors to get every divisor
e.g. Find the divisors of 20
The square root of 20 is 4.47 so we choose 4.
20 mod 1 == 0 so we add 1 and 20/1 a.k.a. 20 to our list of divisors
20 mod 2 == 0 so we add 2 and 20/2 a.k.a 10 to our list of divisors
20 mod 3 == 2 so we ignore this one.
20 mod 4 == 0 so we add 4 and 20/4 a.k.a. 5 to our list of divisors
Therefore the divisors are 1, 2, 4, 5, 10 and 20.
Another good efficiency improvement is that all perfect numbers will end in 6 or 28 so you can quickly check that.
The last efficiency improvement I know is a big change to the prime calculation bit.
If a number is smaller than or equal to 1 it is not prime.
Else if a number is smaller than or equal to 3 it is prime.
Else if a number mod 2 or a number mod 3 == 0 it is not prime.
Set i to 5
While i squared is smaller than or equal to a number:
If a number mod i or a number mod (i + 2) == 0:
It is not prime
6 is added to i
If nothing has said otherwise then the number is prime.

Related

Looping with conditional statement

Hi i want to learn how to do java loop that will determined the number if it is an odd or even like
1st value: 8
2nd value: 15
output:
8 is even
9 is odd
10 is even
11 is odd
12 is even
13 is odd
14 is even
15 is odd
You can do it like so:
Scanner input = new Scanner(System.in);
System.out.print("First value: ");
int start = Integer.parseInt(input.nextLine());//Gets the first number
System.out.print("Second value: ");
int end = Integer.parseInt(input.nextLine());//Gets the second number
for(int i = start; i <= end; i++){
if(i%2==0){//When the number is divided by 2, it gives a remainder of 0. Modulus helps us get the remainder.
System.out.println(i+" is even");
}else{//Doesn't satisfy the first condition. It must be odd.
System.out.println(i+" is odd");
}
}
We use a Scanner to read the user input, then use a for loop and leverage modulus (%). Modulus calculates the remainder of a number after dividing it by a certain number. If a number divided by 2 gives a remainder of 0, that means it is divisible by 2. We can construct an if statement to check whether it is divisble.
Test Run
First value: 1
Second value: 10
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even
Hey you can use a for loop it's simple.
for(int i=8;i<=15;i++){
if(i%2==0){
System.out.println(i+"is even");
}else{
System.out.println(i+"is odd");
}
}
And I expect you know how to ask inputs so just pass it on the place of 8 and 15
The short version:
https://www.youtube.com/watch?v=cakN0XC6CcQ
Use number % 2 == 0 for even numbers.
The long version:
// Create a new Scanner() to scan System.in
Scanner scanner = new Scanner(System.in);
// Get the two inputs
int first = scanner.nextInt();
int second = scanner.nextInt();
// Start i as the first number
// While it is less than or equal to the second
// Add one each time
for(int i = first; i <= second; i++) {
// Is there a remainder from dividing i by 2?
// If no, it's even
boolean even = i % 2 == 0;
// Print it
System.out.println(i + " is even: " + even);
}
scanner.close();

Is there better way of iteration to find the evenly divisible number?

I'm trying to solve this problem:
"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"
Please, do not tell me the answer, I really want to solve it by myself. All I need is an advice regarding math aspect of the question. The thing is adding one every cycle isn't a good idea because the process is too slow. Or is there a problem with variable type not being long?
I've tried to get number which is evenly divisible of all numbers between (1 and 10), and even (1 and 17), and the algorithm worked well.
int in_num = 1;
int score = 0;
public void calculate() {
while (true) {
score = 0;
for (int x = 1; x < 21; x++) {
if ((in_num%x) == 0) {
score++;
}
}
System.out.println("Number " + in_num + " has " + score );
if (score == 20) {
System.out.println(in_num);
break;
}
in_num++;
}
I expect the specific integer, but I get infinite loop.
Isn't this enough?
Multiply every prime number from 1 to 20 to get the number! Also instead of 2 use 16 and instead of 3 use 9.
Long number = 2 ^ 4 * 3 ^ 2 * 5 * 7 * 11 * 13 * 17 * 19L;
System.out.println(number);
Detailed Answer:
We need to find every prime number less than 20. After that, for each prime number, we must calculate the number to which we can exponentiate the prime number while it stays less than 20.
For example, if we multiply 2 four times with itself it remains below 20 (16). But if we calculate 2 to the fifth, it will be 32 which is greater than 20.
We will do the same for every other prime number. By this calculation the actual answer will be like this:
Long number = 2 ^ 4 * 3 ^ 2 * 5 ^ 1 * 7 ^ 1 * 11 ^ 1 * 13 ^ 1 * 17 ^ 1 * 19L ^ 1;
The lowest common multiple of two numbers x and y is xy/GCD(x,y), where GCD calculates the greatest common divisor.
You can implement GCD easily using Euclid's algorithm or the binary GCD algorithm: https://en.wikipedia.org/wiki/Greatest_common_divisor
The algorithm would be like:
result = 1;
for (x = 20; x > 0; --x)
result *= (x/GCD(x,result));
Of course this works for other numbers as well. If you really don't care about that, then you can just print 232792560
You are getting an infinite loop because of int (in_num) range exceeded its length; replace type int to Long (something bigger than int) you will not get any infinite loop and you will get your output.

Code doesn't print the correct number of repeated digits

So basically this is a method to print numbers from 0 to n but squared. And to return the number of digits "d" contained in the numbers from 0 to n.
So let's say n=10 and d=1, we will have 0 1 4 9 16 25 36 49 64 81 100 and the method should return 4 since there are 4 ones in this set of numbers.
This works fine, but when n is defined with a bigger integer that's where the method starts to return an incorrect number of digits.
for instance, if we have n=5750 and d=0, the method returns 3012 when it's supposed to return 4700. Where did I do wrong?
public static int numberOfDig(int n, int d) {
String output="";
for(int i=0;i<=n;i++){
output+=(int)Math.pow(i, 2)+" ";
}
String[] numbers=output.split(" ");
String digit= Integer.toString(d);
int count =0;
for(int i=0;i<numbers.length;i++){
if(numbers[i].contains(digit))count++;
}
return count;
}
Please don't hesitate to ask questions if you need further explanations.
Your problem is that you only increment your count by one when a number contains the digit d. You need to increment by the number of times d occurs in each number.
The relevant code is:
if (numbers[i].contains(digit))
count++;
So if d == 5 and numbers[i] == 25, you increment count by 1 which is correct.
However, if d == 0 and numbers[i] == 100 you increment count by 1 which is incorrect. You should increment by 2 (as there are two zeroes).
A simple test would be n=10 and d=1, where output will be 0 1 4 9 16 25 36 49 64 81 100 121. Your method will return 5 as there are five numbers that contain a 1, whereas it should return 6 as 121 contains two instances of 1.

Re-running the program in the same run

Write a program that reads integers, finds the largest of them, and counts its occurrences. Assume that the input ends with number 0. Suppose that you entered 3 5 2 5 5 5 0; the program finds that the largest is 5 and the occurrence count for 5 is 4.
Design the program such it allows the user to re-run the
program with a different inputs in the same run.
public void findLargestInteger(){
//create Scanner object
Scanner input = new Scanner(System.in);
int x;
do {
//prompt user input
System.out.print("Enter an integer, the input ends if it is 0:");
//declare variables
int n, countNeg = 0, countPos = 0;
float sum = 0;
//calculate how many positive and negative values, total, and average
while ((n = input.nextInt()) != 0) {
sum = sum + n;
if (n > 0) {
countPos++;
}
else if (n < 0) {
countNeg++;
}
}
//display results
if (countPos + countNeg == 0) {
System.out.println("No numbers are entered except 0");
System.exit(0);
}
System.out.println("The number of positives is " + countPos);
System.out.println("The number of negatives is " + countNeg);
System.out.println("The total is " + sum);
System.out.println("The average is " + (sum / (countPos + countNeg)));
}while ((x = input.nextInt()) != 0);
}
How can I get the prompt to display correctly at the end and keep it
running?
Output:
Enter an integer, the input ends if it is 0:
1 2 3 0
The number of positives is 3
The number of negatives is 0
The total is 6.0
The average is 2.0
1
Enter an integer, the input ends if it is 0:
1 2 3 0
The number of positives is 3
The number of negatives is 0
The total is 6.0
The average is 2.0
1
Enter an integer, the input ends if it is 0:
2 3 4 0
The number of positives is 3
The number of negatives is 0
The total is 9.0 The average is 3.0
1
Enter an integer, the input ends if it is 0:
2 3 4 0
The number of positives is 3
The number of negatives is 0
The total is 9.0
The average is 3.0
You could change while((x = input.nextInt()) != 0); to while(true); if you really want to keep repeating your program.
That IS an infinite loop though which is not really a good way to go.
So instead of looking for the next integer and compare with 0, maybe you should write something like
System.out.print("Do you want to quit? (y/n): ");
at the end of your loop (right before the while((x = input.nextInt()) != 0) line).
And then not check for 0 but for the y. At least then you don't have the program waiting for the user to input something without knowing what's happening.
Edit: Or you can just use a counter if you want to run it like twice or three times before it terminates ;)
Have you tried just calling your function inside a while loop?
public void findLargestInteger() {
// Your code
}
public static void main(String[] args) {
do {
findLargestInteger();
Scanner reader = new Scanner(System.in); // Reading from System.in
System.out.println("Would you like to continue? (0/1) ");
int n = reader.nextInt();
} while(n == 1);
}

Write statements in Java reads two integers and displays even numbers between them

Write statements that can be used in a Java Program two integers and display the number of even integers that lie between them. For example, the number of even integers that lie between 12 and 5 are 4
So far below is what i have.... the program outputs all the numbers between the two integers, and not the actual number of even integers.
Can someone please help / tell me what i am doing wrong ?
import java.util.Scanner;
public class evenNumberPrinter {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter the smaller integer");
int numOne = keyboard.nextInt();
System.out.println("Enter the larger integer");
int numTwo = keyboard.nextInt();
for (int i = numOne; i <= numTwo; i++) {
System.out.println(i + " ");
}
}
}
to calculate count of even numbers you don't have to use for loop, here is the formula:
static long evenCount(long a, long b) {
return ((Math.abs(a - b) + 1) >>> 1) + ((~((a & 1) | (b & 1))) & 1);
}
some clarification:
zero (0) is even number
count of even numbers obviously depends on distance between two values, lets pull some data:
0-0 - 1 number, distance 0 (0)
0-1 - 1 number, distance 1
0-2 - 2 numbers, distance 2 (0, 2)
0-3 - 2 numbers, distance 3
0-4 - 3 numbers, distance 4 (0, 2, 4)
0-5 - 3 numbers, distance 5
0-6 - 4 numbers, distance 6 (0, 2, 4, 6)
1-1 - no even, distance 0
1-2 - 1 number, distance 1 (2)
so, count of even numbers is determined by (distance+1)/2 plus one if both numbers are even
so, if we take distance Math.abs(a-b) + 1 divide it by two (>>>1) and then add 1 if and only if both numbers are even (a&1)==0
Another solution is to use pure math:
round the smaller number to the next even number (e.g. 5 to 6)
round the bigger number to the previous even number (e.g. 13 to 12)
subtract from the bigger rounded the smaller, e.g. 12-6 = 6
since even numbers are every second, divide it by 2 plus add one to count the first number of the range as well, that is 3+1=4
That is:
public static void main(final String[] args) {
final int number1=1;
final int number2=6;
int min=Math.min(number1, number2);
int max=Math.max(number1, number2);
min=min+min%2; // round up
max=max-max%2; // round down
final int evens=(max-min)/2+1; // even range plus the first number
System.out.println(evens); // Look ma, no loops
}
Edited to include explanation
Your for loop is doing nothing more than printing each number between numOne and numTwo. What you want to do is check to see if i is even or odd which can be accomplished using the modulus operator if i modulus 2 equals zero, then that number is even, and you should increment a counter variable each time this is true.
Change your for loop to something like this:
int evenCounter = 0;
for (int i = numOne; i < numTwo; i++){
if (i % 2 == 0){
System.out.print(i + " ");
evenCounter++;
}
}
System.out.println("There are " + evenCounter + " even numbers between " +
numOne + " and " + numTwo);
A little more optimal solution (if you want to print the numbers). Testing for parity (odd vs even) can be done only once, before entering the loop. Afterwards, just stay on even numbers by incrementing by 2.
int n = numOne;
int evenCount = 0;
if ((n%2)==1) { n++; }
while (n <= numTwo) {
System.out.println(n);
n += 2;
evenCount ++;
}
System.out.println( "There are " + evenCount + " even numbers between " + numOne + " and " + numTwo );
However, if your goal is only to determine how many there are (not print them), this is not optimal. A mathematical solution will be much faster.
int n = 0; //this is your counter
for (int i = numOne; i < numTwo; i++) { //use < numTwo instead of <= numTwo
//so it doesn't count numTwo as an int between your range
if (i%2 == 0) {n++;} //checks to see if number is even
// if it is, it adds one to the counter and moves on
}
System.out.println("there are " +n+ "even numbers between " +numOne+ " and " +numTwo); //prints out how many even ints were counted.

Categories

Resources