我尝试了下面的项目欧拉编码挑战,代码给出的答案是正确的,但我不明白为什么它需要近一分钟才能运行。在使用筛子之前,它的完成时间相似。其他用户报告的时间低至毫秒。
我认为我在某个地方犯了一个基本错误......
// The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
// Find the sum of all the primes below two million.
public static long Ex010()
{
var sum = 0L;
var sieve = new bool[2000000];
var primes = new List<int>(10000);
for (int i = 2; i < sieve.Length; i++)
{
if (sieve[i-1])
continue;
var isPrime = true;
foreach (var prime in primes)
{
if (i % prime == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primes.Add(i);
sum += i;
for (var x = i * 2; x < sieve.Length; x += i) {
sieve[x-1] = true;
}
}
}
return sum;
}
EDIT:
唯一似乎缺少的是这个优化:
if (prime > Math.Sqrt(i))
break;
它将时间缩短至 160 毫秒。
EDIT 2:
最后点击,按照多次建议取出 foreach。现在是 12 毫秒。最终解决方案:
public static long Ex010()
{
var sum = 0L;
var sieve = new bool[2000000];
for (int i = 2; i < sieve.Length; i++)
{
if (sieve[i-1])
continue;
sum += i;
for (var x = i * 2; x < sieve.Length; x += i) {
sieve[x-1] = true;
}
}
return sum;
}
除了筛子之外,你还进行了试除。
布尔数组已经告诉您一个数字是否是素数,因此您根本不需要素数列表。
您还可以通过仅筛选至极限的平方根来加快速度。
如果你还想节省一些内存,你可以使用BitArray而不是布尔数组。
public static long Ex010()
{
const int Limit = 2000000;
int sqrt = (int)Math.Sqrt(Limit);
var sum = 0L;
var isComposite = new bool[Limit];
for (int i = 2; i < sqrt; i++) {
if (isComposite[i - 2])
continue;//This number is not prime, skip
sum += i;
for (var x = i * i; x < isComposite.Length; x += i) {
isComposite[x - 2] = true;
}
}
//Add the remaining prime numbers
for (int i = sqrt; i < Limit; i++) {
if (!isComposite[i - 2]) {
sum += i;
}
}
return sum;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)