Scala性能-筛子 [英] Scala performance - Sieve

查看:122
本文介绍了Scala性能-筛子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在,我正在尝试学习Scala.我从小开始,写了一些简单的算法.当我想通过发现所有低于特定阈值的所有质数来实现Sieve算法时,遇到了一些问题.

Right now, I am trying to learn Scala . I've started small, writing some simple algorithms . I've encountered some problems when I wanted to implement the Sieve algorithm from finding all all prime numbers lower than a certain threshold .

我的实现是:

import scala.math

object Sieve {

    // Returns all prime numbers until maxNum
    def getPrimes(maxNum : Int) = {
        def sieve(list: List[Int], stop : Int) : List[Int] = {
            list match {
                case Nil => Nil
                case h :: list if h <= stop => h :: sieve(list.filterNot(_ % h == 0), stop)
                case _ => list
            }
        }
        val stop : Int = math.sqrt(maxNum).toInt
        sieve((2 to maxNum).toList, stop)
    }

    def main(args: Array[String]) = {
        val ap = printf("%d ", (_:Int)); 

        // works
        getPrimes(1000).foreach(ap(_))

        // works 
        getPrimes(100000).foreach(ap(_))

        // out of memory
        getPrimes(1000000).foreach(ap(_))

    }
}

不幸的是,当我想计算所有小于1000000(100万)的质数时,它失败了.我收到了OutOfMemory.

Unfortunately it fails when I want to computer all the prime numbers smaller than 1000000 (1 million) . I am receiving OutOfMemory .

您对如何优化代码或如何以更优雅的方式实现此算法有任何想法.

Do you have any idea on how to optimize the code, or how can I implement this algorithm in a more elegant fashion .

PS:我在Haskell中做了非常相似的事情,在那里我没有遇到任何问题.

PS: I've done something very similar in Haskell, and there I didn't encountered any issues .

推荐答案

我将使用无限流.使用惰性数据结构可以像在Haskell中一样进行编码.它会自动读取比您编写的代码更声明性"的代码.

I would go with an infinite Stream. Using a lazy data structure allows to code pretty much like in Haskell. It reads automatically more "declarative" than the code you wrote.

import Stream._

val primes = 2 #:: sieve(3)

def sieve(n: Int) : Stream[Int] =
      if (primes.takeWhile(p => p*p <= n).exists(n % _ == 0)) sieve(n + 2)
      else n #:: sieve(n + 2)

def getPrimes(maxNum : Int) = primes.takeWhile(_ < maxNum)

显然,这不是最有效的方法.阅读真正的Eratosthenes筛子(它是Haskell,但不太困难).对于真正的大范围,您应该考虑阿特金筛子.

Obviously, this isn't the most performant approach. Read The Genuine Sieve of Eratosthenes for a good explanation (it's Haskell, but not too difficult). For real big ranges you should consider the Sieve of Atkin.

这篇关于Scala性能-筛子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆