我编写了以下代码来计算和输出素数。
我得到的素数在控制台上输出,并存储在文本文件中。
计算所有数字直到指定的数字。
有关使此代码运行更快的任何建议更有效率?
static void Main(string[] args)
{
long i;
long j;
for (i = 3; i < 10000000; i += 2)
{
bool isPrime = true;
for (j = 2; j <= i / 2; j++)
{
if (i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
Console.WriteLine(i);
using (System.IO.StreamWriter StreamWriter = System.IO.File.AppendText(@"C:\Users\Marco\Documents\Visual Studio 2012\Projects\Prime Number Generator\Prime Number Generator\bin\Debug\Prime List.txt"))
{
StreamWriter.WriteLine(i);
}
}
}
}
由于
答案 0 :(得分:1)
您需要在sqrt(i)
之前检查除法,而不是i/2
。 (正如@ I4V在下面的评论中正确指出的那样,j*j < i
将比j < sqrt(i)
更快,因为平方根是一个非常慢的操作cmp。到乘法)
您可以在循环中使用以前找到的素数(即将它们存储在数组中并循环遍历它们),因为您只需要通过素数检查可分性。
只有在优化算法之后,才能开始优化代码。
答案 1 :(得分:1)
您使用的算法称为试验分区,如果您在@sashkello和@giuliofranco建议的平方根处停留,则它具有时间复杂度O(n ^ 2)或O(n ^ 1.5)。一种更好的算法是两千多年前发明的Eratosthenes筛,其时间复杂度为O(n log log n),几乎为O(n)。 Eratosthenes的Sieve首先列出从2到最大期望素数 n 的所有数字,然后进入迭代阶段。在每一步中,识别出尚未考虑的最小的未交叉数,并且该数的所有倍数都被划掉;重复这一过程直到没有未交叉的数字仍未被考虑。所有未交叉的数字都是素数。
function primes(n)
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve[p]
output p
for i from p*p to n step p
sieve[i] := False
在primes
函数中,sieve
是数字列表,当sieve[p]
为True
时,未交叉的数字按升序排列,并作为素数输出被考虑,并且“交叉”的倍数由 i 上的循环完成;循环从p*p
开始,因为所有较小的倍数已被较小的素数划掉。
如果你对使用素数进行编程感兴趣,我谦虚地在我的博客上推荐这个essay,它讨论了这个算法,给出了一个优化,它的速度加倍,在质数上提供了许多其他算法,以及提供五种语言的实现。
答案 2 :(得分:0)
1)以sqrt(i)结束你的循环,而不是(i / 2)。保存的时间值得您计算平方根所需的时间。
2)不要忘记你生成的数字。将它们保存到一个数组中(至少是最后一个数组),然后尝试将候选项除以您知道的最佳数字。如果x%y == 0,则y是素数,或者存在素数P 3)如果你真的想要达到最大可达到的速度,你应该使用AKS或Miller-Rabin算法,这些算法可以检查数字在多项式时间内是否为素数(AKS总是正确的,米勒 - 拉宾有时可以说非素数是素数。static void Main(string[] args)
{
long i;
int j;
List<long> primes = new List<long>();
primes.Add(2);
long maxJ;
using (System.IO.StreamWriter StreamWriter = System.IO.File.AppendText(@"C:\Users\Marco\Documents\Visual Studio 2012\Projects\Prime Number Generator\Prime Number Generator\bin\Debug\Prime List.txt"))
{
for (i = 3; i < 10000000; i += 2)
{
//Compute only once, rather that at each iteration
maxJ = (long)Math.Sqrt(i);
for (j = 0; j < primes.Count && primes[j] <= maxJ; ++j)
{
if (i % primes[j] == 0)
{
goto EndOfOuterLoop;
}
}
Console.WriteLine(i);
StreamWriter.WriteLine(i);
primes.Add(i);
EndOfOuterLoop:
}
}
}