我是Scala的新手,刚刚写了这个程序:
def isPrime(num: Int, primes: scala.collection.mutable.MutableList[Int]): Boolean = {
primes.takeWhile( i => i * i <= num).forall( num % _ > 0)
}
//def isPrime(num: Int, primes: scala.collection.mutable.MutableList[Int]): Boolean = {
// !primes.forall(num%_!=0)
//}
def primeListUnder(upper: Int) = {
val primes=scala.collection.mutable.MutableList(2,3);
var num=4
while(num<upper) {
if(isPrime(num,primes))
{
primes+=num
}
num+=1
}
primes
}
这是试图在指定的上限下得到所有素数。但它运行得很慢。 有什么建议吗?
添加了: 其实我的观点是要知道为什么这个程序运行得如此之慢。它不是关于如何计算素数。
编辑: 更改了isPrime方法,首先过滤掉一些数字(数学上)。 现在跑的速度要快得多,在我的Mac上大约需要10秒才算到2000000;
答案 0 :(得分:0)
要列出少于特定数字的所有素数,您应该使用Sieve of Eratosthenes。 它比你的算法快得多。
你的算法是如此缓慢,因为它检查每个数字所有素数小于它,直到找到它的除数。因此,每个号码都将使用至少一个素数进行检查。 但是当检查数量增加时,素数列表会增加,并且可能的检查数量会增加。
经过多次检查后,会有数字被拒绝。 例如,在检查2,3,5,7,11,13后,将拒绝26号。
此外,在检查所有更少的素数后,将接受每个素数。
与您的算法相比,Sieve of Eratosthenes算法将触及&#39;每个号码都标记为&#39; prime&#39;或者&#39;不是素数&#39;。
答案 1 :(得分:0)
正如@rtruszk所提到的,以下代码从my answer on the other linked question重新发布,用于真正的Eratosthenes筛选(SoE)将比您的更大范围的代码运行得快得多:
object SoE {
def makeSoE_Primes(top: Int): Iterator[Int] = {
val topndx = (top - 3) / 2
val nonprms = new scala.collection.mutable.BitSet(topndx + 1)
def cullp(i: Int) = {
import scala.annotation.tailrec; val p = i + i + 3
@tailrec def cull(c: Int): Unit = if (c <= topndx) { nonprms += c; cull(c + p) }
cull((p * p - 3) >>> 1)
}
(0 to (Math.sqrt(top).toInt - 3) >>> 1).filterNot { nonprms }.foreach { cullp }
Iterator.single(2) ++ (0 to topndx).filterNot { nonprms }.map { i: Int => i + i + 3 }
}
}
上面的代码主要是函数形式(使用尾递归或更高阶函数以及除用于快速筛选复合数字的BitSet数组的内容之外的不可变性)。它不像使用Java.util.BitSet那么快,但结果代码稍微优雅。