关于Scala性能调优的问题

时间:2014-10-31 09:17:39

标签: performance scala

我是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;

2 个答案:

答案 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那么快,但结果代码稍微优雅。