Finding factors of a given integer - java

I have something like this down:
int f = 120;
for(int ff = 1; ff <= f; ff++){
while (f % ff != 0){
}
Is there anything wrong with my loop to find factors? I'm really confused as to the workings of for and while statements, so chances are they are completely wrong.
After this, how would I go about assigning variables to said factors?

The following code will return a list of all factors of a given number:
public ArrayList<Integer> findFactors(int num) {
ArrayList<Integer> factors = new ArrayList<Integer>();
// Skip two if the number is odd
int incrementer = num % 2 == 0 ? 1 : 2;
for (int i = 1; i <= Math.sqrt(num); i += incrementer) {
// If there is no remainder, then the number is a factor.
if (num % i == 0) {
factors.add(i);
// Skip duplicates
if (i != num / i) {
factors.add(num / i);
}
}
}
// Sort the list of factors
Collections.sort(factors);
return factors;
}
This answer improves Sharad Dargan's answer in two ways:
Based on an idea used in this answer, you can speed up the solution by determining the value to increment by, based on whether the number is even or odd.
Add the following line of code before the for loop:
int incrementer = num % 2 == 0 ? 1 : 2;
Then change the last part of the loop to:
i += incrementer
If the number is odd, it then will skip all even numbers, rather than always incrementing by one no matter what.
Sharad stores the upper limit value in a variable and then uses that variable in the for loop:
int upperlimit = (int)(Math.sqrt(a));
...
for(int i = 1; i <= upperlimit; i+= 1)
Instead, place Math.sqrt(num) directly in the for loop and skip the upper limit variable:
for (int i = 1; i <= Math.sqrt(num); i += incrementer) {
This will allow you to skip the casting part of the code, creating cleaner code.
Some JUnit test cases you can then use:
#Test
public void test12() {
FindFactors find = new FindFactors();
int num = 12;
List<Integer> factors = Arrays.asList(1, 2, 3, 4, 6, 12);
assertEquals(factors, find.findFactors(num));
}
#Test
public void test1000000() {
FindFactors find = new FindFactors();
int num = 1000000;
List<Integer> factors = Arrays.asList(1, 2, 4, 5, 8, 10, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200,
250, 320, 400, 500, 625, 800, 1000, 1250, 1600, 2000, 2500, 3125, 4000, 5000, 6250, 8000, 10000, 12500,
15625, 20000, 25000, 31250, 40000, 50000, 62500, 100000, 125000, 200000, 250000, 500000, 1000000);
assertEquals(factors, find.findFactors(num));
}
#Test
public void test1() {
FindFactors find = new FindFactors();
int num = 1;
List<Integer> factors = Arrays.asList(1);
assertEquals(factors, find.findFactors(num));
}
#Test
public void test0() {
FindFactors find = new FindFactors();
int num = 0;
List<Integer> factors = new ArrayList<Integer>();
assertEquals(factors, find.findFactors(num));
}

Here is how to get all factors of the given number.
public class Factors {
public static void main(String[] args){
int n = 420;
for(int i=2; i<=n; i++){
while(n%i==0){
System.out.println(i + "| " + n);
System.out.println(" -----");
n = n/i;
}
}
}
}
Output:
2| 420
-----
2| 210
-----
3| 105
-----
5| 35
-----
7| 7
-----

public class Solution {
public ArrayList<Integer> allFactors(int a) {
int upperlimit = (int)(Math.sqrt(a));
ArrayList<Integer> factors = new ArrayList<Integer>();
for(int i=1;i <= upperlimit; i+= 1){
if(a%i == 0){
factors.add(i);
if(i != a/i){
factors.add(a/i);
}
}
}
Collections.sort(factors);
return factors;
}
}
The above solution simply works like calculating prime factors.
The difference being for every prime factor we keep calculating the other part of the product i.e the reqd number.

In order to find the factors of a given number, you only need to check upto the square root of the given number.
For example, in order to find the factors of 6, you only need to check till 2.45 (√6). The factors of 6 will be 1 and 2, and their converse numbers, i.e. 3 and 6.
I have made a program that determines the factors of a given number and displays them. Here is the necessary code:
Scanner input = new Scanner(System.in);
System.out.print("Enter integer: ");
long num = input.nextLong();
for(long i = 1; i <= Math.sqrt(num); i++) {
if(num % i == 0) {
System.out.println(i);
if(i != num/i) {
System.out.println(num/i);
}
}
}
You just need this program to find the factors of a given number. However, if you want to take it a step further and display the factors arranged in ascending order, then the necessary code is as follows:
Scanner input = new Scanner(System.in);
System.out.print("Enter integer: ");
long num = input.nextLong();
ArrayList<Long> list1 = new ArrayList<>(), list2 = new ArrayList<>();
long currentTime = System.currentTimeMillis();
for(long i = 1; i <= Math.sqrt(num); i++) {
if(num % i == 0) {
list1.add(i);
if(i != num/i) {
list2.add(num/i);
}
}
}
int n1 = list1.size() - 1;
int n2 = list2.size() - 1;
for(int i = 0; i <= n1; i++) {
System.out.println(list1.get(i));
}
for(int i = n2; i >= 0; i--) {
System.out.println(list2.get(i));
}
What this does: This program stores the factors of the number upto the number's square root in one list (list1), and the converse of these numbers in another list (list2). It then prints the elements of both lists (as shown).

There's nothing wrong with your for loop, but a while loop is the wrong thing to be using here.
The logic of your for loop is:
Set ff to 1.
Keep going while ff <= f.
After you've done everything in the for loop, add 1 to ff.
This looks like it is exactly as you want.
The while loop isn't right, though. It will continue to do whatever code you write there for as long as ff is a factor of f, so unless you change them in the while code, you'll get an infinite loop. However, changing that to an if statement will give you what you want.
Since you're checking for factors, you don't actually need to check all possibilities up to f - only up to the square root of f. Whenever you find that ff is a factor, output both ff and f/ff as factors, unless f is a sqare number.

public static void printFactors(int number) {
if (number < 1 )
System.out.println("Invalid Value");
for (int i = 1 ; i <= number ; ++i) {
if ( number % i == 0)
System.out.println(i);
}
}
}

It looks like you are not going to do something with either f or ff in your while loop? If so, the expression f%ff != 0 is either false (and then it will go to the next in the for loop), or it is true, and it will end up in an infinite loop.
Are you sure you need the while like this?

Slightly modified solution: You can first check if variable x is divisible by variable y. If yes, we will count 1 and will repeat this process. For the loop counter, x/y is used and you should check x>0 to avoid repetition when x becomes zero but loop is not finished yet.
public class Factor {
public static void main(String[] args) {
int x = 48;
int x1 = x;
int y = 2;
int k = x / y;
int j = 0;
for (int i = 1; i < k; i++) {
if ((x % y) == 0 && x > 0)
j++;
x = x / 2;
}
System.out.println(+x1 + " is a factor of " + y + " for " + j
+ " times.");
}
}

I got all the factors just fine with this (I just modified the algorithm in the question).
int num1 = 120;
for(int num2=1;num2<=num1;num2++)
{
if (num1%num2 != 0)
System.out.println(num2);
}

import java.util.Scanner;
public class Factors
{
Scanner scn=new Scanner(System.in);
int num=scn.nextInt();
public void findFactor()
{
System.out.println("Factors are");
System.out.println("1");
for(int i=2;i<=num;i++)
{
if(num%i==0)
{
num=num/i;
System.out.println(i);
i=2;
}
}
}
public static void main(String[] args)
{
while(1==1)
{
System.out.println("Enter a Number");
Factors fct=new Factors();
fct.findFactor();
}
}
}

Utilizing Streams introduced in Java 8, the following will print the factors for a given number.
int input = 1500;
IntStream.rangeClosed(1, input)
.filter(e -> input % e == 0)
.forEach(System.out::println);

This is how you write it yourself like a boss. Needs to add if statements to handle one and two, but besides that; this method is as sexy as it gets
public static void primerize(int n){
boolean reduced = false;
while(n > 2){
if(n%2 == 0){
System.out.println(2 + "," + n/2);
n /= 2;
}
else{
int i = isPrime(n);
if(i == n && reduced == false){
System.out.println(1 + "," + n);
n /= n;
}
else if(i == n){
n/= n;
}
else{
System.out.println(i + "," + n/i);
n = i;
reduced = true;
}
}
}}
public static int isPrime(int n){
for(int i = (n/3); i > 0; i--){
if(i == 1){
return n;
}
else if(n%i == 0){
return i;
}
}
return 0;}

This code will give you the factors.
ArrayList<Integer> arr = new ArrayList<>();
int x=48;
int y=1;
while(x!=1)
{
if(x%y==0)
{
x=x/y;
arr.add(y);
if(y==1)
{
y++;
}
}
else
{
y+=1;
}
}
System.out.println(arr);

Easiest way using recursive function
public static int factorial(int n){
if(n!=1)
return n*factorial(n-1);
return 1;
}

Related

Armstrong Number Checker in Java

I am still somewhat of a beginner to Java, but I need help with my code. I wanted to write an Armstrong Number checker.
An Armstrong number is one whose sum of digits raised to the power three equals the number itself. 371, for example, is an Armstrong number because 3^3 + 7^3 + 1^3 = 371.
If I understand this concept correctly, then my code should work fine, but I don't know where I made mistakes. I would appreciate if you could help correct my mistakes, but still kind of stick with my solution to the problem, unless my try is completely wrong or most of it needs to change.
Here is the code:
public class ArmstrongChecker {
boolean confirm = false;
Integer input;
String converter;
int indices;
int result = 1;
void ArmstrongCheck(Integer input) {
this.input = input;
converter = input.toString();
char[] array = converter.toCharArray();
indices = array.length;
result = (int) Math.pow(array[0], indices);
for (int i = 1; i < array.length; i++) {
result = result + (int) Math.pow(array[i], indices);
}
if (result == input) {
confirm = true;
System.out.println(confirm);
} else {
System.out.println(confirm);
}
}
}
For my tries I used '153' as an input. Thank you for your help!
You aren't summing the digits, but the numeric values of the characters representing them. You can convert such a character to its numeric value by subtracting the character '0':
int result = 0;
for(int i = 0; i < array.length; i++) {
result = result + (int) Math.pow(array[i] - '0', indices);
}
Having said that, it's arguably (probably?) more elegant to read the input as an actual int number and iterate its digits by taking the reminder of 10 on each iteration. The number of digits itself can be calculated using a base-10 log.
int temp = input;
int result = 0;
int indices = (int) Math.log10(input) + 1;
while (temp != 0) {
int digit = temp % 10;
result += (int) Math.pow(digit, indices);
temp /= 10;
}
There is a small logical mistake in your code, You're not converting the character to an integer instead you're doing something like
Math.pow('1', 3) -> Math.pow(49, 3) // what you're doing
Math.pow(1, 3) // what should be done
You should first convert the character to the string using any method below
result = (int) Math.pow(array[0],indices);
for(int i = 1;i<array.length;i++) {
result = result + (int) Math.pow(array[i],indices);
}
For converting char to integer
int x = Character.getNumericValue(array[i]);
or
int x = Integer.parseInt(String.valueOf(array[i]));
or
int x = array[i] - '0';
Alternatively
You can also check for Armstrong's number without any conversion, using the logic below
public class Armstrong {
public static void main(String[] args) {
int number = 153, num, rem, res = 0;
num = number;
while (num != 0)
{
rem = num % 10;
res += Math.pow(rem, 3);
num /= 10;
}
if(res == num)
System.out.println("YES");
else
System.out.println("NO");
}
}
For any int >= 0 you can do it like this.
Print all the Armstrong numbers less than 10_000.
for (int i = 0; i < 10_000; i++) {
if (isArmstrong(i)) {
System.out.println(i);
}
}
prints
0
1
2
3
4
5
6
7
8
9
153
370
371
407
1634
8208
9474
The key is to use Math.log10 to compute the number of digits in the candidate number. This must be amended by adding 1. So Math.log10(923) returns 2.965201701025912. Casting to an int and adding 1 would be 3 digits.
The number of digits is then the power used for computation.
Then it's just a matter of summing up the digits raised to that power. The method short circuits and returns false if the sum exceeds the number before all the digits are processed.
public static boolean isArmstrong(int v) {
if (v < 0) {
throw new IllegalArgumentException("Argument must >= 0");
}
int temp = v;
int power = (int)Math.log10(temp)+1;
int sum = 0;
while (temp > 0) {
sum += Math.pow(temp % 10, power);
if (sum > v) {
return false;
}
temp/= 10;
}
return v == sum;
}

Program that displays every perfect number

My code runs but for one of the tests two outputs are printed when I only need one. I am unsure of how to avoid this.
This is the task:
Write an application that displays every perfect number from 2 through 1,000. A perfect number is one that equals the sum of all the numbers that divide evenly into it. For example, 6 is perfect because 1, 2, and 3 divide evenly into it and their sum is 6; however, 12 is not a perfect number because 1, 2, 3, 4, and 6 divide evenly into it, and their sum is greater than 12.
The provided template lays out the initial for loop to check each number beginning from 2 and going up to 1,000. In this for loop, the perfect() method is called, where you will submit your piece of code to test if each number follows the conditions described above.
Set result to true if it meets those conditions and use sum to add up the numbers divisible by int n in the method's parameter.
public class Perfect{
public static void main (String args[]){
final int MAX = 1000;
for(int i = 2; i <= MAX; i++)
if(perfect(i) == true)
System.out.println("The number " + i + " is perfect");
}
public static boolean perfect(int n){
int sum = 1;
int i;
boolean result = false;
for (i = 2; i < n / 2; i++) {
if (n % i == 0) {
sum += i;
}
}
if (sum == i) {
return true;
}
else {
return false;
}
}
}
My output:
The number 496 is perfect
The number 729 is perfect
Expected output:
The number 496 is perfect
It only expects the first line printed...
You need to compare sum to the original number n, not to i. And you need to add 1 to the loop condition or it will miss the last divider in even numbers
public static boolean perfect(int n){
int sum = 1;
for (int i = 2; i < (n / 2) + 1; i++) {
if (n % i == 0) {
sum += i;
}
}
return sum == n;
}
First, I don't know if you have used the correct formula. But, you should know that the first perfect number are 6, 28, 496 and 8128. 729 is not a perfect number.
Hope it helped.
public static void main(String[] args) {
int i, j, s;
System.out.println("Perfect numbers 1 to 1000: ");
for(i=1;i<=1000;i++){
s=0;
for(j=1;j<i;j++){
if(i%j==0){
s=s+j;
}
}
if(i==s){ //if i == s is perfect
System.out.println(i);
}
}
}
}
According to the question, you have to print all perfect numbers.
I have created a small snippet, try it and see.
public void printPerfect() {
for(int i=2;i<1000;i++) {
List<Integer> l =factors(i);
int sum =0;
for (Integer factor : l) {
sum+=factor;
}
if(sum==i) {
System.out.println("perfect-- " +i);
}
}
}
List<Integer> factors(int number) {
List<Integer> l = new ArrayList<Integer>();
for(int i = 1; i <= number; ++i) {
if (number % i == 0) {
if(i!=number)
l.add(i);
}
}
return l;
}
You checked sum == i instead of sum == n.
As 729 = 3^6 : 3, 243, 9, 81, 27.
public static boolean perfect(int n) {
int sum = 1;
for (int i = 2; i <= n / 2 && sum <= n; i++) {
if (n % i == 0) {
sum += i;
}
}
return sum == n;
}

To find out Armstrong number in between numbers

Below is my code.
package com.ofss.java.examples;
import java.util.Scanner;
class ArmstrongNumber {
public static void main(String[] args) {
int c = 0, a;
int n1, n2;//Range in which armstrong number need to find
Scanner s = new Scanner(System.in);
System.out.println("Enter the first number");
n1 = s.nextInt();
System.out.println("Enter the second number");
n2 = s.nextInt();
for (int i = n1; i <= n2; ++i) {
while (i > 0) {
a = i % 10;
System.out.println(a);
i = i / 10;
System.out.println(i);
c = c + (a * a * a);
System.out.println(c);
}
if (i == c)
System.out.println(c + "armstrong number");
else
System.out.println(c + "Not armstrong number");
}
}
}
I am getting incorrect results after executing. Code runs for infinite number till you stops it. It must print number between 151-154 (153 as armstrong).
Also, it is incorrectly printing 153 as not Armstrong number.
Armstrong Number
...is a number that is the sum of its own digits each raised to the power of the number of digits.
You should not change i since this is also used in
for (int i = n1; i <= n2; ++i)
Or you will probably never exit that loop eiter since you expect i to be negative at the end of the first iteration. Hard to increment until it reach n2.
Use a different variable to keep track of i safely.
int j = i;
while(j > 0) ...
About Armstrong number:
Armstrong number is a number that is the sum of its own digits each raised to the power of the number of digits
You need to put each digit to the power of the length of the number (the number of digit).
153 = 1^3 + 5^3 + 3^3
1634 = 1^4 + 6^4 + 3^4 + 4^4
Here is the method for it :
public static boolean isArmstrongNumber(int number){
int power = Integer.toString(number).length(); //just to get the number of digit...
int tmp = number;
int digit , sum = 0;
while(tmp > 0){
digit = tmp % 10;
sum += Math.round(Math.pow(digit , power));
tmp /= 10;
}
return sum == number;
}
Using this check from 0 to 10.000 gives :
0
1
2
3
4
5
6
7
8
9
153
370
371
407
1634
8208
9474
Same as Wikipedia :
The sequence of base 10 narcissistic numbers starts: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474, ...
Note that using a method remove the risk of forgetting to reset your variable like c in your case. Correcting this would give you a few more "correct" results (well the one with 3 digits)
You can also use less mathematics to read the number and use char[], remember that you need to substract '0' value to get the numeric value for a character :
public static boolean isArmstrongNumber(int number){
char[] digits = Integer.toString(number).toCharArray();
int power = digits.length;
int sum = 0;
for(char c : digits){
int digit = c - '0';
sum += Math.round(Math.pow(digit, power));
}
return sum == number;
}
There are two things.
you are updating i everytime as you have used it in while, so use different variable than i for this calculation.
int num = i;
c is used to compare sum of cube is same as number but you are not resetting it once the one iteration is over. so make c=0 inside for loop.
c = 0;
Also while printing you are using c, there should be i which is correct and real number.
Below is the working code you may try.
public static void main(String[] args)
{
int c = 0, a;
int n1, n2;//Range in which armstrong number need to find
Scanner s = new Scanner(System.in);
System.out.println("Enter the first number");
n1 = s.nextInt();
System.out.println("Enter the second number");
n2 = s.nextInt();
for (int i = n1; i <= n2; ++i)
{
int num = i;
while (num > 0)
{
a = num % 10;
num = num / 10;
c = c + (a * a * a);
}
if (i == c)
System.out.println(i + "armstrong number");
else
System.out.println(i + "Not armstrong number");
c = 0;
}
}
public class ArmstrongNumber {
private final int n1, n2;
public ArmstrongNumber(int n1, int n2) {
this.n1 = n1;
this.n2 = n2;
}
protected static boolean isArmstrong(int n) {
if(n < 0)
return false;
int remaining=n;
int sumCube=0;
while (remaining>0) {
int d = remaining % 10;
sumCube += cube(d);
remaining /= 10;
}
return n == sumCube;
}
private static int cube(int d) {
return d*d*d;
}
public Integer[] find() {
List<Integer> results = new ArrayList<>();
for (int i = n1; i <= n2; ++i)
{
if (isArmstrong(i))
results.add(i);
}
return results.toArray(new Integer[0]);
}
}
There are lot of things to improve in your code. One of the working logics as below:
for (int i = n1; i <= n2; ++i) {
int sum = 0, remainder = 0, digits = 0, temp = 0;
temp = i;
while (temp != 0) {
digits++;
temp = temp / 10;
}
temp = i;
while (temp != 0) {
remainder = temp % 10;
sum = sum + (int) Math.pow(remainder, digits);
temp = temp / 10;
}
if (i == sum)
System.out.println(i + " is an Armstrong number.");
else
System.out.println(i + " isn't an Armstrong number.");
}

Given a positive int n, print “Has 1” if it contains a 1 digit otherwise print “Has No 1”

public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
for(int i = n; i >= 0; i = n / 10)
{
i = i % 10;
if(i == 1)
System.out.print("Has 1");
n /= 10;
}
System.out.print("Has No 1");
}
It's working with "Has 1", but it's not printing anything when there is no digit 1. What's missing?
The logic of your current code won't do what you wish to achieve. Cause it is going in infinite loop (for both cases with 1 and not 1 numbers) because you are continuing the loop when i >= 0 and i won't be negative for any positive numbers in the loop. Since the 1 case is within the loop, so it prints that statement.
Moreover, even if you correct the loop then it will still execute
System.out.print("Has No 1");
No matter if there is one in the given number or not.
You need to update this code to the following
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
boolean hasOne = false;
int rem;
for(int i = n; i > 0; i = i / 10)
{
rem = i % 10;
if(rem == 1)
hasOne = true;
}
if(hasOne){
System.out.println("Has 1");
}else{
System.out.println("Has No 1");
}
Hope this helps
A helper method makes it easy and reusable:
private static String hasDigit(int n, int digit) {
for (int i = n; i > 0; i /= 10)
if (i % 10 == digit)
return "Has " + digit;
return "Has No " + digit;
}
Test
System.out.println(hasDigit(13579, 1));
System.out.println(hasDigit(24680, 1));
System.out.println(hasDigit(13579, 2));
System.out.println(hasDigit(24680, 2));
Output
Has 1
Has No 1
Has No 2
Has 2

Prime numbers in a given range with less complexity

I have used below programs to find first n prime numbers (in below program it is from 2 to n). Can we write a program with single for loop? I also tried recursive approach but it is not working for me.
public static void main(String[] args) {
// Prime numbers in a range
int range = 15;
int num = 1;
int count = 0;
boolean prime = true;
while (count < range) {
num = num + 1;
prime = true;
for (int i = 2; i <= num / 2; i++) {
if (num % i == 0) {
prime = false;
break;
}
}
if (prime) {
count++;
System.out.println(num);
}
}
}
i dont think you can reduce it to one loop. But you can improve your code as Luca mentioned it.
public class PrimeFinder {
private final List<Integer> primes;
private final int primeCapacity;
public PrimeFinder(final int primeCapacity) {
if (primeCapacity < 3) {
throw new IllegalArgumentException("Tkat is way to easy.");
}
this.primeCapacity = primeCapacity;
primes = new ArrayList<>(primeCapacity);
primes.add(2);
}
public void find() {
final Index currentNumber = new Index();
while (primes.size() < primeCapacity) {
if (!primes.stream().parallel().anyMatch(prime -> (currentNumber.value % prime) == 0)) {
primes.add(currentNumber.incremet());
} else {
currentNumber.incremet();
}
}
}
public List<Integer> getPrimes() {
return primes;
}
private class Index {
public int value = 3;
public int incremet() {
return value++;
}
}
public static void main(String[] args) {
PrimeFinder primeFinder = new PrimeFinder(100000);
final long start = System.currentTimeMillis();
primeFinder.find();
final long finish = System.currentTimeMillis();
System.out.println("Score after " + (finish - start) + " milis.");
primeFinder.getPrimes().stream().forEach((prime) -> {
System.out.println(prime);
});
}
}
main rule here is simple, if given number isnt clearly divided by any prime number that you already have found, then it is prime number.
P.S. dont forget that primes.strem().... is loop also, so it is not a one loop code.
P.S.S. you can reduce this much further.
to understand the complexity of your algorithm you don't have to count the number of inner loops but the number of times you are iterating over your elements. To improve the performance of your algorithm you need to investigate if there are some iterations that could be unnecessary.
In your case when you do
for (int i = 2; i <= num / 2; i++) you are testing your num against values that are not necessary.. ex: if a number is divisible by 4 it will be by 2 too.
when you do for (int i = 2; i <= num / 2; i++) with num = 11
i will assume the values 2,3,4,5. 4 here is a not interesting number and represent an iteration that could be avoided.
anyway according to wikipedia the sieve of Eratosthenes is one of the most efficient ways to find all of the smaller primes.
public class PrimeSieve {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
// initially assume all integers are prime
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
}
}
}
// count primes
int primes = 0;
for (int i = 2; i <= N; i++) {
if (isPrime[i]) primes++;
}
System.out.println("The number of primes <= " + N + " is " + primes);
}
}
I don't know any way use a single loop for your question, but I do see two places where you can reduce the complexity:
Cache the prime numbers you found and use these prime numbers to decide if a number is prime or not. For example, to decide if 11 is a prime number, you just need to divide it by 2,3,5,7 instead of 2,3,4,5,6,...10
You don't need to check till num/2, you only need to check till the square root of num. For example, for 10, you only need to check 2,3 instead of 2,3,4,5. Because if number n is not prime, then n = a * b where either a or b is smaller than the square root x of n). If a is the smaller one, knowing that n can be divided by a is enough to decide that n is not prime.
So combining 1 & 2, you can improve the efficiency of your loops:
public static void main(String[] args) {
// Prime numbers in a range
int range = 15;
int num = 1;
int count = 0;
boolean prime = true;
ArrayList<Integer> primes = new ArrayList<>(range);
while (num < range) {
num = num + 1;
prime = true;
int numSquareRoot = (int) Math.floor(Math.pow(num, 0.5));
for (Integer smallPrimes : primes) {// only need to divide by the primes smaller than num
if (numSquareRoot > numSquareRoot) {// only need to check till the square root of num
break;
}
if (num % smallPrimes == 0) {
prime = false;
break;
}
}
if (prime) {
System.out.println(num);
primes.add(num);// cache the primes
}
}
}

Categories