关于c#:项目欧拉号10#


Project euler number 10#

1
2
3
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.

我的答案是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool IsRishoni;
int soap = 0;
for (int i = 3; i < 2000000; i++)
{
    IsRishoni = true;
    for (int a = 2; (a <= Math.Sqrt(i)) && (IsRishoni); a++)
    {
        if (i % a == 0)
            IsRishoni = false;
    }
    if (IsRishoni)
    {
        soap = i + soap;
    }
}
Console.WriteLine(soap + 2);
Console.ReadLine();

为什么这不起作用? 我得到的答案是1179908154 ...请帮助。


更换

1
soap = i + soap;

1
soap = checked(i + soap);

..问题应该暴露出来。

这个问题有更多详细信息:C#中的int是否没有溢出异常?


您的答案(存储在soap中)的值大于int.Maxvalue(2,147,483,647)。

您的答案是?15,000,000,000

换句话说,您需要使用大于该数据类型的数据类型。

1
2
long.MaxValue = 9,223,372,036,854,775,807
int.Maxvalue = 2,147,483,647


您追求的结果可能太大,无法通过32位带符号整数(int)表示。

首先,假设所有数字均为质数,从而确定结果的上限。通过求和,我们知道直到N(含)以下的所有数字的总和为N * (N + 1) / 2;因此,所有素数之和的上限为2,000,000,即2,000,001,000,000。该值大于int所允许的最大值2,147,483,647,因此您可能会遇到数值溢出,而该溢出将被忽略。

如果您想对答案进行更准确的估计,可以使用素数定理,该定理指出0到N之间的随机整数为素数的概率约为1 / ln(N)。将此与我们以前的公式结合起来,直到N的所有素数的近似总和为N * (N + 1) / (2 * ln(N))。对于2,000,000,这大约等于138,000,000,000,仍然大于int的最大值。

要解决您的问题,只需将用于soap变量的整数数据类型切换为64位整数表示形式,例如long。其最大值为9,223,372,036,854,775,807,因此绝对可以代表您的电话号码。

1
long soap = 0;

单独说明:由于您正在使用素数序列,因此,如果将实现更改为Eratosthenes筛网,则可以实现巨大的性能提升(至少100倍)。