简体   繁体   English

查找第10001个素数-代码未返回正确的数

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

To avoid any misunderstanding, I'm new here and still a beginner in Java. 为避免任何误解,我是这里的新手,并且仍然是Java的初学者。 I'm trying to write a code that prints the 10,001st prime number. 我正在尝试编写一个打印第10,001个素数的代码。 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. 该代码当前检查数字是否可被数字2-9(含2-9)整除,然后检查数字的平方根是否为整数。

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. 例如,当检查数字143时,您的代码认为它是质数。 However, 11*13 = 143, so it is actually not prime. 但是,11 * 13 = 143,因此它实际上不是素数。 I suggest creating a List of the prime numbers and doing a for-each loop through the List. 我建议创建素数列表,并在列表中进行for-each循环。

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. 例如,数字437不是质数,因为它是19 * 23,但是它将通过您当前的测试。

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. 您的新版本无法正常工作,因为您正在测试Math.sqrt(Num)所有降为1的数字,而不是降为2的所有数字。1始终准确地出现在每个数字中,因此您的程序不会认为有任何数字是启动,并永远运行。

To make it work you need to change while(i>0) to while(i>1) . 为了使其工作,您需要将while(i>0)更改为while(i>1) You also need to change if(i==0) to if(i==1) . 您还需要将if(i==0)更改为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. 我也不确定为什么NumCounter值分别是8和4。我将留给您弄清楚它们应该是什么。

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): 在这里,您会发现使用Stream类的另一种(紧凑的)方式来生成由const MAX(生成的元素数)限制的素数序列(对于生成的每个x,过滤器都会拒绝x不能被x整除的x :一个数字只能被自身整除,而1是质数):

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... 输出:[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. 我会使用基于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. 问题在于,由于您不知道第10001个素数是多少,因此您不知道要制造多大的阵列。 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. 您可以尝试考虑一些较大的数字,并希望它足够大以容纳10001个素数,但是如果它太大,您将需要做更多的工作。 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.). 假设您从一个大小为1000的布尔数组(例如,代表1到1000的数字)开始。执行筛分(以2开头;将2添加到列表中,在数组中标记2的所有倍数,找到下一个未标记的值,将其添加到列表中,标记该列表的所有倍数,依此类推)。 This obviously won't find the 10001st prime. 这显然找不到10001st素数。 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. 因此,当您到达布尔数组的末尾时,请清除它,然后更改“基本”变量,以便现在它表示1001到2000范围内的数字。遍历已建立的素数列表,然后标记所有倍数。 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. 将它们添加到列表中,清除数组,然后更改基数,以使数组现在将数字表示为2001到3000。遍历素数列表,标记倍数,并继续进行操作,直到列表大小达到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. 我不知道这种方法与其他方法相比有多有效,但是从直觉上看,这似乎比逐个检查所有数字并检查每个数字的除数要好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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