加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么这个scala prime代这么慢/内存密集?

发布时间:2020-12-16 09:26:13 所属栏目:安全 来源:网络整理
导读:我在找到第10,001个素数时耗尽了内存. object Euler0007 { def from(n: Int): Stream[Int] = n #:: from(n + 1) def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.filter(_ % s.head != 0)) def primes = sieve(from(2)) def main(args: Array[
我在找到第10,001个素数时耗尽了内存.

object Euler0007 {
  def from(n: Int): Stream[Int] = n #:: from(n + 1)
  def sieve(s: Stream[Int]): Stream[Int] = s.head #:: sieve(s.filter(_ % s.head != 0))
  def primes = sieve(from(2))
  def main(args: Array[String]): Unit = {
    println(primes(10001))
  }
}

这是因为在每次“迭代”(这是这个上下文中的正确术语吗?)之后,我增加要调用的函数堆栈以使下一个元素一个一个?

我在网上发现的一个解决方案是不使用迭代解决方案(我想避免进入函数式编程/惯用scala)是this(问题7):

lazy val ps: Stream[Int] = 2 #:: Stream.from(3).filter(i => ps.takeWhile(j => j * j <= i).forall(i % _ > 0))

从我所看到的,这不会导致这种类似递归的方式.这是一个很好的方法吗,或者你知道更好的方法吗?

解决方法

这种情况缓慢的一个原因是它不是Eratosthenes的筛子.阅读 http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf以获得详细解释(示例在Haskell中,但可以直接转换为Scala).

我对欧拉问题#7的旧解决方案也不是“真正的”筛子,但它对于小数字似乎工作得很好:

object Sieve {

    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 main(args: Array[String]) {
      println(primes(10000)) //note that indexes are zero-based
    }
}

我认为你的第一个版本的问题是你只有defs而且没有val来收集结果,并且可以通过生成函数查阅,所以你总是从头开始重新计算.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读