我正在解决 Project Euler 问题,我目前排在第 10 位。
首先:我知道还有其他解决方案,我目前正在使用 Eratosthenes 的筛子编写另一种方法。我需要您的帮助是了解为什么此代码不起作用。
这是我的代码(问题涉及找到 200 万以下的每个素数的总和)。质数检查方法似乎工作正常,但结果远低于应有的结果。
class Euler10
{
public static void Main()
{
long sum = 0; // Was originally an int. Thanks Soner Gönül!
for(int i = 1; i < 2000000; i++)
{
if (CheckIfPrime(i) == true)
sum += i;
}
System.Console.WriteLine(sum);
System.Console.Read();
}
static bool CheckIfPrime(int number)
{
if (number <= 1)
return false;
if (number == 2)
return true;
if (number % 2 == 0)
return false;
for (int i = 3; i*i < number; i += 2)
{
if ((number % i) == 0)
return false;
}
return true;
}
}
我得到的数字是 1,308,111,344,比它应该的低两个数量级。代码很简单,我对这个错误感到困惑。
编辑:使 sum 长期解决了数字问题,谢谢大家!不过,现在我得到 143042032112 作为答案:CheckIfPrime() 中的 i*i 并不总是正确的。使用 sqrt() 函数并加一(以补偿 int 强制转换)可以得到正确的结果。这是正确的 CheckIfPrime() 函数:
bool CheckIfPrime(int number)
{
if (number <= 1)
return false;
if (number == 2)
return true;
if (number % 2 == 0)
return false;
int max = 1 + (int)System.Math.Sqrt(number);
for (int i = 3; i < max; i += 2)
{
if ((number % i) == 0)
return false;
}
return true;
}
编辑 2: Ness 会帮助我进一步优化代码(计算数字的平方根并将其与 i 进行比较比提升 i^2 然后将其与数字进行比较要慢):原始方法的问题在于它没有考虑到考虑其中 number 是 i 的确切平方的边缘情况,因此有时返回 true 而不是 false。CheckIfPrime() 的正确代码是:
bool CheckIfPrime(int number)
{
if (number <= 1)
return false;
if (number == 2)
return true;
if (number % 2 == 0)
return false;
for (int i = 3; i*i <= number; i += 2)
{
if ((number % i) == 0)
return false;
}
return true;
}
再次感谢人们!