简体   繁体   中英

return an array of prime numbers

I need a method to return prime numbers in an array.

So if given: primeArray(5)

than an array like so should be returned: (2, 3, 5)

For some reason this doesn't seem to work for me:

public static int[] primeArray(int numFind)
{
    //determines the size of the array returned
    int primeTotal = 0;

    //loop to find total prime numbers
    for (int j = 1; j <= numFind; j ++)
    {
        if (isPrime(j))
        primeTotal +=1;
    }

    //declare array to be returned
    int[] numA = new int[primeTotal];

    //current index of prime number
    int iP = 0;

    //loop to add prime elements to array
    for (int x = 1; x <= numFind; x ++)
    {
        if (isPrime(x))
        {
            numA[iP]=x;
            iP++;    // <--- THIS IS CAUSING ME PROBLEMS
        }

    }

    return numA;
}

public static boolean isPrime(int n)
{
    for (int i = 2; i < n; i++)
    {
        if(n%i==0)
            return false;
    }
    return true;
}

This is what I'm using to test my code:

    int[] num = primeArray(11);

    System.out.println(num[0]);
    System.out.println(num[1]);

But for output I'm getting this:

1 
2

If however I comment out the iP++; than the if statement finally decides to execute ONLY when prime numbers are passed as a parameter in: isPrime(j) but then if defeats the whole purpose of the primeArray method because I need the primeArray method to return an array of prime numbers.

Your isPrime() method is faulty. You need to return false , for number < 2 . Also, you don't need to iterate till n , just iterate till n / 2 or even better sqrt(n) .

Change it to:

public static boolean isPrime(int n) {

    if (n < 2) return false;

    int maxIteration = Math.ceil(Math.sqrt(n));

    for (int i = 2; i < maxIteration; i++) {
        if(n % i == 0)
            return false;
    }

    return true;
}

Now, given your real problem (Note that your method is just fine. It would return you correct result, given you changed your isPrime() method), but you can avoid iterating twice by using an ArrayList instead of array :

List<Integer> primes = new ArrayList<Integer>();

//loop to find total prime numbers
for (int j = 1; j <= numFind; j ++)
{
    if (isPrime(j))
        primes.add(j);
}

And then you can just return primes , and change the return type of method to List<Integer> instead of int[] .

public static List<Integer> primeNumberList(int numFind)

If you really want to return an int[] , then you need to do some work converting the ArrayList to an int array. I leave this task to you. Just search for this on SO only, you will get too many posts.


Also, if you are going to generate all prime numbers till a very large number, then you should take a look at Sieve of Eratosthenes

You just do the output for the first to Array-Values...

just replace your output

for(int i = 0; i < num.length; i++)
{
    System.out.println(num[i]);
}

Your code works fine.

In your isPrime() method, add this one statement at the end

if(n < 2) return false;

I think in the current way, when 1 is passed you get a true.

Another suggestion that I can think of is you can use a static table for some amount of numbers if you expect your limit to be small.

static int[] PRIME_TABLE = {2,3,5,7,11,13,17,19,23,29,31}; etc

So when the limit is smaller than 32 in this example, you don't need to calculate all the prime numbers below it and just loop through this table and return the numbers.

I tried to write isPrime(int num) function in a bit different way. The code becomes a bit more lengthy but works. I used a different logic to identify if the number is 1 , because 1 is neither prime nor composite. Code is below.

   static int count=0;
   static boolean flag;
public static boolean isPrime(int num){

    for(int i = 1; i<=num/2 ; i++){

        if(num%i ==0){

            count++;

            if(count >=2){

                flag = false;    
            }
            else{
                  if( num/1==1){
                      flag = false;
                  }
                  else{
                      flag = true;
                  }

            }

         }
    }
        return flag;
  }

this code return all prime numbers less than n

public ArrayList<Integer> allPrimesLessThanN( int n) {

    int sqrtN = (int)Math.sqrt(n);
    int [] numberList = new int[n];
    ArrayList<Integer> primeList = new ArrayList<>();

    for( int i = 0; i < n ; i++) 
    {
        numberList[i] = i+1;
    }

    int k = 2;
    while( k <= sqrtN)
    {
        if(numberList[k+1] != 0)
        {
            for( int j = k+1; j < n; j++)
            {
                if( numberList[j] % k == 0)
                {
                    numberList[j] = 0;
                }
            }
        }

        k++;
    }

    for( int i = 1; i < n; i++)
    {
        if(numberList[i] != 0)
            primeList.add(numberList[i]);
    }

    return primeList;

}

There are a few ways to get an array of prime numbers, the easiest computationally is to use a Sieve of Eratosthenes . This iterates over every increasing number, where when the next prime is found, all subsequent multiples of this are marked not prime. Most implementations use a boolean array as below:

boolean[] numbers = new boolean[max];
// At first, assume every number is prime
for (int i = 0; i < max; i++) 
    numbers[i] = true; 
// Zero and one are not primes
numbers[0] = number[1] = false;

// Begin iteration from 2, the smallest prime
for (int i = 2; i < max; i++) {
    // if i is prime, all multiples of i are not prime
    if (numbers[i]) {
        for (int j = i * 2; j < max; j += i) {
            numbers[j] = false;
        }
    }
}

This method is good for a quick way to generate an array of primes, but it can get very memory-intensive for large maximum limits.

An alternate way of going about this problem is the way you have done it, where you simply add the next prime number when you find it. Your implementation though could become more efficient from the following.

boolean isPrime(double p) {
    if (p < 2) return false;
    for (int i = 2; i <= Math.sqrt(p); i++) if (p % i == 0) return false;
    return true;
}

Starting with the corrected implementation suggested by Rohit Jain (as above), you may notice you don't have to test every number less than sqrt(p) . If p is not divisible by n , then it is not going to be divisible by the multiples of n - such we only need to test every prime number below p . For example; since 7 is not divisible by 2, it's not going to be divisible by 4 either.

The problem here is that we now need to find which numbers less than sqrt(p) are prime to test against p. Ah, but no we don't! We can just look into our cached list of known primes we will be later returning in the other method. And while we're caching a list of known primes, we don't need to make a new list in the other method either, we can just return our cache (once generated)! The finished product will look something like this:

class Primes {

    private static final List<Double> known_primes = new ArrayList<Double>(Collections.singletonList(2d));

    public static boolean isPrime(double p) {
        if (p < 2) return false; // 2 already in our cache
        if (known_primes.contains(p)) return true; // found prime in cache
        for (double i = 3; i <= Math.sqrt(p); i += 2) { // only check odd numbers
            if (!isPrime(i)) continue; // only check primes
            if (p % i == 0) return false; // p is divisible by i, so not prime
        }
        // checked all possible divisors, so p must be prime - cache and sort it!
        known_primes.add(p);
        Collections.sort(known_primes);
        return true;
    }

}

Now you can use Primes.isPrime(...) to check ;)

public class Demo {
public static void main(String[] args) {
    int result[] = ArrayOfPrimeNumbers(30);
    for (int i = 0; i < result.length; i++) {
        System.out.println("Factor: " + result[i]);
    }
}
public static int[] ArrayOfPrimeNumbers(int n) {
    int countPrimeNumbers = 0;
    for (int i = 2; i <= n; i++) {
        if (isPrime(i)) {
            countPrimeNumbers++;
        }
    }
    int newArrayofPrime[] = new int[countPrimeNumbers];
    int count = 0;
    while (count < countPrimeNumbers) {
        for (int i = 2; i <= n; i++) {
            if (isPrime(i)) {
                newArrayofPrime[count] = i;
                count++;
            }
        }
    }
    return newArrayofPrime;
}
public static boolean isPrime(int n) {
    if (n <= 1)
        return false;

    for (int i = 2; i < n; i++)
        if (n % i == 0)
            return false;

    return true;
}

}

You can way more optimize it by using Sieve algorithm to find primes. Following implementation can find primes upto (10^9)-1.

#include<iostream>//for I/O
#include<vector>//for keeping primes
#include<math.h>//for sqrt()
#define lli long long int
using namespace std;
vector<lli>prime;//using long long int data type for getting result for relatively bigger numbers...you may use int if you are working with smaller numbers.
lli upto;
bool stat[100000001];//Status array to keep track for primes/non-primes (0=prime, 1=non-prime, initially all are 0)
void sieve(lli upto)
{
    lli n=upto;
    stat[0]=stat[1]=1;//Marking 0 and 1 as they are not primes
    for(lli i=4;i<=n;i+=2)//Marking all even numbers as they won't be primes
    {
        stat[i]=1;
    }
    lli sqrtn=sqrt(n);
    //You can check if a number is prime or not just by making sure it is not divisible by any numbers upto it's square-root.
    //The reason of not checking the numbers after that is that if the number is divisible by a number greater than or equal to its square-root,
    //then we surely have already found another number which also divides the number less than or equal to its square root. For example to check if 36 is
    //a prime we can try dividing it with numbers <=sqrt(36) or <=6.We need not go beyond it. Say we need not check with 9 or 12 etc. as we have already checked
    //the divisibility with their conjugates 4 and 3 respectively (as 4*9=36 and 3*12=36) and found that 36 is getting divided, hence non prime.
    for(lli i=3;i<=sqrtn;i+=2)//So continuing this loop upto sqrt(n) and starting from 3 and stepping to only the odd numbers,as we cannot expect an even number to be a prime (except 2)
    {
        if(stat[i]==0)//ith index is still unmarked means it is a prime
        {
            //..so leaving ith index unmarked we are marking all the multiples of i as number i will divide them and they won't be primes.
            //But again we can do some optimizations:
            //(1) The next unmarked number divided by i, greater than i will be i*i. Because numbers less than i*i which is also divided by i are already marked by some numbers<i. An example will make it clear:
            //    Say for 5 we will start marking from 5*5=25, although 15 is divided by 5 but we need not mark it again as it is already marked by 3 (as 3 also divides 15) when we worked with 3.
            //(2) We are advancing our checking 2*i times as we are now searching for primes in odd numbers only, so we are skipping the marking for even numbers (say for 3, starting check from 3*3=9, we will next check 9+2*i=9+2*3=15 (we skipped checking 12 as it is even and we have already marked all even numbers initially (except 2) for being non-primes).
            for(lli j=i*i;j<=n;j+=2*i)
            {
                stat[j]=1;//so marking the indexes corresponding to numbers which are divisible by j as they are non-primes.
            }
        }
    }
    for(lli i=2;i<=n;i++)
    {
        if(stat[i]==0)//Finally finding which are still unmarked as the are not divisible by any number (except divisible by 1 and the number itself as prime number's definition) and the numbers corresponding to these indexes are primes.
        {
            prime.push_back(i);//storing primes, as index i is unmarked so i is a prime.
        }
    }
}
int main()
{
    cout<<"Enter upto which number you want to look for primes: ";
    cin>>upto;
    sieve(upto);
    for(int i=0,z=prime.size();i<z;i++)//printing
    {
        cout<<prime[i]<<" ";
    }
    cout<<endl;
}

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