简体   繁体   中英

Finding the 10001st Prime Number - Code not returning correct number

To avoid any misunderstanding, I'm new here and still a beginner in Java. I'm trying to write a code that prints the 10,001st prime number. The code currently checks whether the number is divisible by numbers 2-9 (inclusive) and then checking if the square root of the number is a whole number or not.

public static void main(String[] args){
  Integer Num , Counter;
  Double Sqrt; //square root
  Num=8;
  Counter=4 ;
  while(Counter<10001){
    Num++;
    if ((Num%2!=0) && (Num%3!=0) && (Num%4!=0) && (Num%5!=0) && (Num%6!=0) && (Num%7!=0) &&   (Num%8!=0) && (Num%9!=0)){
    Sqrt = Math.sqrt(Num);    
    if(Sqrt%1!=0){
      Counter++;
     }
   }
 }

 System.out.println(Num); 
 }
}

Edit:

I changed it so that it no longer uses the false definition, but with this new code there is no output and I don't see any problems with the loop. I will also attempt the other suggestions below but want to know how to fix this.

 public static void main(String[] args)
   {
 int Num , Counter;
 double Sqrt; //square root
 Num=1;
 Counter=0 ;

 while(Counter<10001){
   Num++;
   Sqrt = Math.sqrt(Num);
   int i = (int)Sqrt;
    while(i>1){
       if(Num%i==0){ //if the number is divisible then the loop is terminated and next number is tested
        i=0;
                   }
        i--;
              }

      if(i==1){
     Counter++;
              }
 }

 System.out.println(Num);   
  }
 }

Thanks.

Your logic is flawed. For example, when checking the number 143, your code thinks it is prime. However, 11*13 = 143, so it is actually not prime. I suggest creating a List of the prime numbers and doing a for-each loop through the List.

List<Integer> primes = new ArrayList<Integer>();
int number = 2;
while (primes.size() < 10001) {
   boolean isPrime = true;
   for (Integer prime : primes) {
      if (number % prime == 0) {
         isPrime = false;
         break;
      }
   }
   if (isPrime) {
      primes.add(number)
   }
   number++;
}
System.out.println(primes.get(10000));

This may not be a fast solution but it should work... didn't test though. Good luck :).

It's not working because your definition of a prime number is incorrect.

For instance, the number 437 is not prime, because it is 19 * 23, but it would pass your current tests.

Your algorithm needs to check that the number in question is not divisible by any prime number up to and including the square root of the number you're checking.

Your new version doesn't work because you are testing all numbers from Math.sqrt(Num) down to 1, rather than all numbers down to 2. 1 always exactly goes into every number, so your program doesn't think any number is prime, and runs forever.

To make it work you need to change while(i>0) to while(i>1) . You also need to change if(i==0) to if(i==1) . I'm also not sure why your values for Num and Counter are 8 and 4. I'll leave you to figure out what they should be.

Here you'll find just another (compact) way for generating a sequence of prime numbers limited by the const MAX (num of elements generated), using Stream class (for each x generated, the filter rejects x that is not divisible by x only: a number divisible by only itself and 1 is prime):

public class PrimeNumbersSeq {

    final private static Long MAX=10001l;

    public static void main(String[] args) {
    System.out.println(LongStream
            .iterate(2, x -> x + 1)
            .filter((i) -> LongStream.range(2, i)
            .noneMatch(j -> i % j == 0)).limit(MAX)
            .mapToObj(String::valueOf)
            .collect(Collectors.joining(",", "[", "]")));
    }
}

Output: [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101...

I would use an approach based on the sieve of Eratosthenes. The problem is that since you don't know what the 10001st prime is, you don't know how big to make your array. You could try to think of some big number and hope it's big enough to hold 10001 primes, but if it's way too large you'll be doing extra work. There may be some formulas that would help you come up with an approximation, and start from there.

Another approach is to start with a smaller array and then extend it if needed. Suppose you start with a boolean array of size (say) 1000, representing the numbers 1 to 1000. Perform the sieve (start with 2; add 2 to a list, mark all multiples of 2 in the array, the find the next unmarked value, add it to the list, mark all multiples of that, etc.). This obviously won't find the 10001st prime. So when you hit the end of the boolean array, clear it out and then change a "base" variable, so that now it represents numbers in the range 1001 to 2000. Go through the list of primes you've already built up, and mark all the multiples. Now all the unmarked values are primes. Add them to the list, clear the array, and change the base so that the array now represents the numbers 2001 to 3000. Go through the list of primes, mark multiples, and keep going until your list size reaches 10001.

I don't know how efficient this approach is compared to others, but it intuitively seems like it would be better than going through all numbers one by one and checking each number for divisors.

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