【发布时间】:2010-11-05 18:53:28
【问题描述】:
实现这个功能最优雅的方式是什么:
ArrayList generatePrimes(int n)
此函数生成第一个n 素数(编辑:n>1),因此generatePrimes(5) 将返回一个ArrayList 和{2, 3, 5, 7, 11}。 (我在 C# 中执行此操作,但我对 Java 实现或任何其他类似语言(因此不是 Haskell)感到满意。
我确实知道如何编写这个函数,但是当我昨晚完成时,它并没有像我希望的那样好。这是我想出的:
ArrayList generatePrimes(int toGenerate)
{
ArrayList primes = new ArrayList();
primes.Add(2);
primes.Add(3);
while (primes.Count < toGenerate)
{
int nextPrime = (int)(primes[primes.Count - 1]) + 2;
while (true)
{
bool isPrime = true;
foreach (int n in primes)
{
if (nextPrime % n == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
break;
}
else
{
nextPrime += 2;
}
}
primes.Add(nextPrime);
}
return primes;
}
我不太关心速度,尽管我不希望它明显低效。我不介意使用哪种方法(naive 或 sieve 或其他任何方法),但我确实希望它相当简短并且很明显它是如何工作的。
编辑:感谢所有回复的人,尽管很多人没有回答我的实际问题。重申一下,我想要一段漂亮干净的代码来生成素数列表。我已经知道如何以多种不同的方式来完成它,但是我很容易编写不太清晰的代码。在此线程中,提出了一些不错的选择:
- 我最初拥有的更好的版本(Peter Smit、jmservera 和 Rekreativc)
- 非常干净的 Eratosthenes (starblue) 筛子实现
- 使用 Java 的
BigIntegers 和nextProbablePrime编写非常简单的代码,尽管我无法想象它会特别高效 (dfa) - 使用 LINQ 延迟生成素数列表 (Maghis)
- 将大量素数放入一个文本文件中,并在必要时读取它们 (darin)
编辑 2:我有implemented in C# 这里给出的几个方法,还有一个这里没有提到的方法。他们都有效地找到了前 n 个素数(我有一个 decent method 来寻找提供给筛子的极限)。
【问题讨论】:
-
不,它也不适合 Project Euler :-)
-
最好是让我重新调用 ienumerable
并一个一个地产生 -
我想知道的是生成素数的最少优雅的方法是什么。我在想一些涉及 Access 数据库的事情?
-
为了比较,2008 Haskell code by BMeph:
nubBy (((>1).).gcd) [2..]。它只留下自然数中的非重复项,从 2 开始,同时将gcd与任何先前找到的数字大于 1 的任何数字视为重复。它的效率非常低,产生的素数是二次的。但它是优雅。 -
最优雅,IMO,是Haskell的
import Data.List.Ordered ; let { _Y g = g (_Y g) ; primes = 2 : _Y( (3:) . minus [5,7..] . unionAll . map (\p-> [p*p, p*p+p*2..]) ) },但这当然完全基于意见。