C# ProjectEuler10:简单代码没有给出期望的结果,需要帮助理解原因吗
我正在为kicks解决Euler项目的问题,我目前排名第10 首先:我知道还有其他解决方案,我目前正在编写另一种方法使用埃拉托斯坦筛我希望您能帮助我理解为什么这段代码不起作用 这是我的代码(问题是找到每个素数在200万以下的和)。基本检查方法似乎工作得很好,但结果远远低于它应有的水平C# ProjectEuler10:简单代码没有给出期望的结果,需要帮助理解原因吗,c#,primes,C#,Primes,我正在为kicks解决Euler项目的问题,我目前排名第10 首先:我知道还有其他解决方案,我目前正在编写另一种方法使用埃拉托斯坦筛我希望您能帮助我理解为什么这段代码不起作用 这是我的代码(问题是找到每个素数在200万以下的和)。基本检查方法似乎工作得很好,但结果远远低于它应有的水平 class Euler10 { public static void Main() { long sum = 0; // Was originally an int. Thanks
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;
}
}
类Euler10
{
公共静态void Main()
{
long sum=0;//原来是一个整数。谢谢Soner Gönül!
对于(int i=1;i<2000000;i++)
{
if(CheckIfPrime(i)=真)
总和+=i;
}
系统控制台写入线(总和);
System.Console.Read();
}
静态布尔校验素数(整数)
{
如果(number您的代码不工作,因为它试图使用32位int
来保存一个超过32位变量中最高值的数字。问题的答案是142913828922
,它需要38位
将sum
的数据类型更改为long
应该可以解决此问题。您正在为sum
变量使用32位
,但您试图将其分配给2147483647
的变量
但是您的结果是14304203212
,它需要比32
更多的位来存储它
将其类型设置为存储64
位的类型
long sum = 0;
这里是一个工作模式。使用long应该会有所帮助。
为您提供一个64位整数,其中as int仅为32位。for(…i=3;i*i
错误。它应该是
for (... i=3 ; i*i <= number; i+=2 )
...
对于(…i=3;i*i您的算法不是Eratosthenes的筛;模运算符给出了它。您的算法是用奇数进行试除。下面是一个使用Eratosthenes筛的函数:
function sumPrimes(n)
sum := 0
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve[p]
sum := sum + p
for i from p * p to n step p
sieve[i] := False
return sum
调用sumPrimes(2000000)
给出了答案,出于对Project Euler的尊重,我不会写下这个答案。该函数在时间O(n log n)中运行,这比O(n^2)要好得多有更好的筛选方法,但这很简单,很容易找到正确的方法,对于大多数目的来说都足够好,包括你的。你应该在不到一秒钟的时间内得到答案
我将留给您使用适当的数据类型将其转换为C#
如果你对这个问题的更大版本感兴趣,我在我的博客上计算过:11138479445180240497。@MatthewWatson强制转换是如何防止的?当达到32位值时,我会不会像求和一样停止增加?“这永远不会给你一个溢出,因为你从3开始”限制足够小。如果限制接近类型的限制,可能会溢出。[我知道你知道这一点,但应该说是为了完整性。]我知道这不是筛子,我的意思是我在另一个文件中处理筛子(我想知道为什么这个代码不起作用,而不是有更有效的方法来解决这个问题)非常感谢你的答案,我肯定在检查埃拉托色尼,这不是筛选器,你只是在尝试试用素数来测试。正如其他人注意到的,你超过了32位算术的界限。要考虑两件事:首先,考虑使用校验算法;虽然速度较慢,但是你会发现你的错误。第二,Euler问题将超过64位算法的边界;考虑使用BigTigle。它较慢,但它的范围没有特定的限制。(如果你需要任何精确的理由,微软解决方案基金会有一个合理的类;它是免费下载的。)最后,有很多方法可以加快素数检查的速度。例如,您可以通过检查2和3,然后检查(int i=6;i*i
这样,您就可以检查5、7、11、13、17、19……的可除性,并跳过检查4、6、8、9、10、12、14、15、16……而不是只跳过4、6、8、10、12、14……而不必检查任何已经可以被3除的数字,因为您已经检查过了。
for (... i=3 ; i*i <= number; i+=2 )
...
function sumPrimes(n)
sum := 0
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve[p]
sum := sum + p
for i from p * p to n step p
sieve[i] := False
return sum