简体   繁体   English

查找10001:st素数(Euler项目)

[英]Finding the 10001:st prime number (Euler project)

I am doing challenge 7 on the Euler project, which requires me to find the 10001:st prime number. 我正在对Euler项目进行挑战7,这要求我找到10001:st质数。

My attempt is as follows: 我的尝试如下:

    int i=2; //the number to check if prime
    int c=0; //the amount of prime numbers

    while(true){

        //checks if i%n == 0, if so, i is not a prime number. 
        for(int n=2;n<=prob.getMax(i);n++){
            //it is not a prime number
            if(i%n==0){
                break;
            }

            //it is a prime number 
            if(n==prob.getMax(i)){
                c++;
                break;
            }

        }
        i++;

        //if c == 10001 we have found the 10001:st prime number
        if(c==10001){
            System.out.println(i);
            break;
        }

    }

}

public int getMax(int x){

    return (int) Math.ceil(Math.sqrt(x));

}

I am returned the value 104760 but that does not seem to be correct. 我返回值104760,但这似乎不正确。 I cannot understand what I am doing wrong, since I seem to get a reasonable value. 我无法理解自己在做什么错,因为我似乎获得了合理的价值。 Could anyone point me in the right direction? 有人能指出我正确的方向吗?

And also: is there any better way to compute these kind of problems? 还有:有没有更好的方法来计算这类问题? I seem to be using a for-loop and brute forcing my way to the solution on every problem. 我似乎正在使用for循环和强行将我的方法强制解决每个问题。

You increase i before checking whether the found prime is the 10001st one. 在检查找到的素数是否为10001st之前增加i。 By swapping the order of these actions, it should work. 通过交换这些操作的顺序,它应该可以工作。

You are increasing i (with i++ ) before showing the result. 在显示结果之前,您正在增加i (使用i++ )。 The 100001 prime may be 104760-1. 100001素数可以是104760-1。

One advise, try to avoid those while(true). 一个建议,尽量避免那些while(true)。 You can do something like: 您可以执行以下操作:

c = 0;
while (c < 10001) {
    ....
    c++
}

In your code, you are not checking the prob.getMax(i) which is in for loop. 在您的代码中,您没有检查for循环中的prob.getMax(i) Add another check in the body of your for loop, something like the following: for循环的主体中添加另一个检查,如下所示:

if(n==theDesiredNumber){
 //...
 break;
}

By searching you can find out that the 10001st prime number is 104743. I changed your algorithm to : 通过搜索,您可以找到第10001个素数是104743。我将算法更改为:

public static void main(String... args) {
  int i = 2; //the number to check if prime
  int c = 1; //the counter for prime numbers have found so far

    while (true) {

       if(isPrime(i)){
           c++;
       }

        //if c == 10001 we have found the 10001:st prime number
        if (c == 10001) {
            System.out.println(i);
            break;
        }
        i++;

    }

}

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

public static int getMax(int x) {

    return (int) Math.ceil(Math.sqrt(x));

}

One thing to note for prime numbers is that with the exception of the number 2, they are always odd numbers and you don't have to check if the number is divisible by every number before it. 质数要注意的一件事是,除了数字2之外,它们始终是奇数,您不必检查数字是否可以被之前的每个数字整除。

public class StackOverflow {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // Starting at 1 cause I'm already including 2
        long primeCount = 1; 

        // Start with an odd number cause primes are never even
        long prime = 1;

        Calendar start = Calendar.getInstance();
        while (primeCount < 10001) {
            prime += 2;
            if (isPrime(prime)) {
                primeCount++;
            }
        }

        System.out.println(prime);
        System.out.println(String.format("Elapsed Time: %d ms", Calendar.getInstance().getTimeInMillis() - start.getTimeInMillis()));
    }

    private static boolean isPrime(long prime) {
        if (prime <= 1)
            return false;
        else if (prime % 2 == 0)
            return (prime == 2);
        else
        {
            int divisor = 3;
            double upperLimit = Math.sqrt((double)prime) + 1;

            while (divisor <= upperLimit)
            {
                if (prime % divisor == 0)
                    return false;

                // Skip by two cause an odd number is never evenly divisible by an even number
                divisor +=2;
            }
            return true;
        }
    }
}

Result (!!!!SPOILER ALERT!!!!!) 结果(!!!! SPOILER ALERT !!!!!)

在此处输入图片说明

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

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