我正在解决欧拉计划中的踢球问题,目前排名第十。
首先:我知道还有其他解决方案,我目前正在使用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,比应有的数字低两个数量级。代码是如此简单,我对此错误感到困惑。
编辑:使总和长期解决了数字问题,谢谢大家!但是,现在我得到了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:威尔·内斯(Will Ness)帮助我进一步优化了代码(计算数字的平方根并将其与i进行比较比将i ^ 2升高然后与数字进行比较要慢):原始方法的问题在于它没有考虑到考虑边缘情况,其中数字是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;
}
再次感谢大家!
最佳答案
您的代码不起作用,因为它尝试使用32位int
来保存超过32位变量中最大值的数字。问题的答案是142,913,828,922
,它需要38位。
将sum
的数据类型更改为long
应该可以解决此问题。