【发布时间】:2013-03-04 20:54:37
【问题描述】:
我正在将一个简单的素数生成单线从 Scala 改编为 C#(在其作者对 this blog 的评论中提到)。我想出了以下几点:
int NextPrime(int from)
{
while(true)
{
n++;
if (!Enumerable.Range(2, (int)Math.Sqrt(n) - 1).Any((i) => n % i == 0))
return n;
}
}
它有效,返回的结果与我在运行博客中引用的代码时得到的结果相同。事实上,它的工作速度相当快。在 LinqPad 中,它在大约 1 秒内生成了第 100,000 个素数。出于好奇,我在没有Enumerable.Range() 和Any() 的情况下重写了它:
int NextPrimeB(int from)
{
while(true)
{
n++;
bool hasFactor = false;
for (int i = 2; i <= (int)Math.Sqrt(n); i++)
{
if (n % i == 0) hasFactor = true;
}
if (!hasFactor) return n;
}
}
直观地说,我希望它们以相同的速度运行,或者甚至让后者运行得更快一些。实际上,使用第二种方法计算相同的值(第 100,000 个素数)需要 12 秒 - 这是一个惊人的差异。
那么这里发生了什么?从根本上说,在第二种方法中一定会发生一些额外的事情,它会占用 CPU 周期,或者在 Linq 示例的背景下进行一些优化。有人知道为什么吗?
【问题讨论】:
-
你可以通过打破内部 for 循环来加速它
-
乍一看,我猜你会想在
if块内添加一个break。这将大大提高性能。 -
这就是您的 linq 查询所做的事情,当它找到您的 for 循环完成整个迭代的答案时,它将停止
标签: c# performance algorithm linq