简体   繁体   English

有关Scala性能调整的问题

[英]Questions on Scala performance tunning

I am new to Scala, just wrote this program: 我是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
}

This is trying to get all the prime numbers under some specified upper bound. 这试图使所有质数都低于某个指定的上限。 But it runs really slow. 但是它运行得很慢。 Any suggestions? 有什么建议么?

Added: Actually my point is to know why this program runs so slow. 补充:实际上,我的意思是要知道为什么该程序运行如此缓慢。 It's not about how to calc the prime numbers. 这与如何计算素数无关。

Edit: Changed the isPrime method to first filter out some numbers (mathematically). 编辑:更改了isPrime方法以首先过滤掉一些数字(数学上)。 Now is runs much faster, takes about 10 secs on my mac to count to 2000000; 现在运行速度要快得多,在我的Mac上大约需要10秒才能达到2000000;

To list all prime numbers less then specific number you should use Sieve of Eratosthenes. 要列出所有素数少于特定数的数,应使用Eratosthenes筛。 It is much faster then your algorithm. 它比您的算法快得多。

Your algorithm is so slow becouse it checks every number with all prime numbers less than it until it finds its divisor. 您的算法是如此之慢,因为它会检查所有质数都小于它的质数的每个数,直到找到其除数。 So every number will be checked with at least one prime number. 因此,将用至少一个质数检查每个数字。 But when checked number grows, the list of primes grows and number of possible checks grows. 但是,当支票数量增加时,素数列表也会增加,可能的支票数量也会增加。

There will be numbers rejected after many checks. 经过多次检查后,会有一些号码被拒绝。 For example number 26 will be rejected after checking 2,3,5,7,11,13. 例如,在检查2,3,5,7,11,13之后,数字26将被拒绝。

Additionally every prime number will be accepted after checking all less prime numbers. 另外,在检查所有较少的素数后,将接受每个素数。

Comparing to your algorithm, Sieve of Eratosthenes algorithm will 'touch' every number once marking it as 'prime' or 'not prime'. 与您的算法相比,Eratosthenes算法的“筛子”一旦将其标记为“素数”或“非素数”,就会“接触”每个数字。

As mentioned by @rtruszk, the following code reposted from my answer on the other linked question for a true Sieve of Eratosthenes (SoE) will run much faster than your code for larger ranges: 正如@rtruszk所提到的,以下代码是从我对另一个链接问题 (真正的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 }
  }
}

The above code is mostly of a functional form (using tail recursion or higher order functions as well as immutability other than for the contents of the BitSet array used for fast sieving of composite numbers). 上面的代码主要是函数形式(使用尾部递归或更高阶函数以及不变性,而不是用于快速筛选复合数字的BitSet数组的内容)。 It isn't quite as fast as using the Java.util.BitSet, but the resulting code is slightly more elegant. 它的速度不如使用Java.util.BitSet的速度快,但是生成的代码稍微优雅一些​​。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM