简体   繁体   中英

Java Array saving prime numbers and using it to find next prime

I have a small problem understanding what my teacher wants me to do. What I have made is a code that saves me all the Prime numbers in an Array that can be displayed. But now he wants me to "optimize" the code with, as far as I understand, try to divide a number only by the numbers that are prime. For example : if I have 2,3,5 the next number to be prime is the number that doesn't divide by any of this. So I don't have to try 2,3,4,5 but only 2,3,5 (the numbers that I have in the array). And for example : 2,3,4,5,7 are primes, 10 is not because it divides by 2 then it has to jump on the next number.

public static void main(String[] args) {
    String introducedNumber = JOptionPane.showInputDialog("Introduce a number"); //with JOptionPane imported will ask you a small box for a number
    int number, divider, numberDividing; //declaring the int's

    number = Integer.parseInt(introducedNumber); //converting the input to a int
    int x = 0; //starting X to 0 since its 1st array position
    int[] arrayPrime = new int[number]; //declaring and creating an array
    for (divider = 1; divider <= number; divider++) { //for to run till numbers
        //for that checks if the number divides by any other than himself
        for (numberDividing = 2; (numberDividing < divider) && (divider % numberDividing != 0); numberDividing++) {
        }

        if (numberDividing >= divider) {
            arrayPrime[x] = divider;
            x++;
        }
    }
    for (int i = 0; i < x; i++) {
        System.out.println(arrayPrime[i]);
    }

}

}

At the moment your code to check whether a number is prime is:

    for (numberDividing = 2; (numberDividing < divider) && (divider % numberDividing != 0); numberDividing++) {
    }

    if (numberDividing >= divider) {
        arrayPrime[x] = divider;
        x++;
    }

So it is checking all numbers from 2 to the last prime. But there's no need for it to do that: it only needs to check the primes you already have in your array.

To make your code a bit more readable, I suggest moving your check to a separate private method. I've also renamed x to primeCount :

private boolean isPrime(int number) {
    for (int i = 0; i < primeCount; i++) {
        if (number % arrayPrime[i] == 0)
            return false;
    }
    return true;
}

Then your calling code becomes:

for (int divider = 2; divider <= number; divider++) {
    if (isPrime(divider))
        arrayPrime[primeCount++] = divider;
}

There is another fairly trivial optimisation you can do. You don't need to check any primes that are greater than the square root of the test number because you've already checked smaller factors at that point:

private boolean isPrime(int number) {
    for (int i = 0; i < primeCount; i++) {
        int prime = arrayPrime[i];
        if (prime * prime > number)
            break;
        else if (number % prime == 0)
            return false;
    }
    return true;
}

If you don't want to use a separate method, then:

for (int divider = 2; divider <= number; divider++) {
    boolean isPrime = true;
    for (int i = 0; i < primeCount && isPrime; i++) {
        isPrime = number % arrayPrime[i] > 0;
    }
    if (isPrime)
        arrayPrime[primeCount++] = divider;
}

And, for your future study, here's a more elegant way to achieve the same result using a prime number generator:

public class PrimeGenerator {
    private long current = 1;
    private final List<Long> primes = new ArrayList<>();

    public long next() {
        do {
            current++;
        } while (primes.stream().anyMatch(n -> current % n == 0));
        primes.add(current);
        return current;
    }
}

You were right that you only need to divide new numbers by previously discover primes. What I do below is simply loop through all the discovered primes and use a boolean to keep track of if each number is prime. I also use an ArrayList instead of an array so that there are not numerous unused blocks like in your original array. Hope this helps!

ArrayList<Integer> arrayPrime = new ArrayList<Integer>(); //use array list instead of static array
arrayPrime.add(2); //seed first prime number
boolean isPrime; //boolean to determine if prime

for (divider = 3; divider <= number; divider++) { //loop up to input number, starting at 3

    isPrime = true; //initialize true for each new number

    for (i = 0; i < arrayPrime.size(); i++) { //loop through each previous prime

        if (divider % arrayPrime[i] == 0) { //see if number is divisible by previous prime
            isPrime = false;
            break; //break out of loop
        }
    }

    if(isPrime){ //if it did not divide evenly, it is prime
        ArrayPrime.add(divider);
    }
}

System.out.println(list);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM