我正在将一个简单的素数生成单线从 Scala 改编为 C#(作者在此博客的评论中提到)。我想出了以下内容:
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()
and的情况下重写了它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 示例的背景下进行一些优化。有人知道为什么吗?