Scala 对大数的阶乘有时会崩溃,有时不会

2024-05-08

以下程序经过编译和测试,有时返回结果,有时充满屏幕

java.lang.StackOverflowError
at scala.BigInt$.apply(BigInt.scala:47)
at scala.BigInt.equals(BigInt.scala:129)
at scala.runtime.BoxesRunTime.equals(Unknown Source)
at bigint$.factorial(fact2.scala:3)
at bigint$.factorial(fact2.scala:3)
...

该程序:

object bigint extends Application {
  def factorial(n: BigInt): BigInt = if (n == 0) 1 else n * factorial(n-1)
  println("4391! = "+factorial(4391))
}

我的问题:

  • 是不是因为JVM上存在堆栈溢出,有时会发生有时不发生?
  • 这种不确定性行为是否被视为错误?
  • 我认为 Scala 没有尾递归这个?我怎样才能使它尾递归呢?

Details:

Scala 编译器版本 2.7.5.final -- 版权所有 2002-2009,LAMP/EPFL Scala 代码运行器版本 2.7.5.final -- 版权所有 2002-2009,LAMP/EPFL

java 版本“1.6.0_0”OpenJDK 运行时环境(构建 1.6.0_0-b11) OpenJDK 客户端虚拟机(版本 1.6.0_0-b11,混合模式,共享)

Ubuntu 2.6.24-24-通用


如果递归调用是函数中的最后一个语句,则尾部调用优化仅在 Scala 中起作用。这是非常有限的。 Scala 书中说:

[...]尾调用优化是 仅限于以下情况 方法或嵌套函数调用自身 直接作为最后一个操作, 不经过函数值 或者其他一些中介。

在您的情况下,递归调用是较大表达式的一部分,并且本身并不是最后一个操作 - 这里的最后一个操作是乘法。

本文 http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and-trampolines.html演示如何使其工作:

class Factorial {
  def factorial(n: Int): Int = {
    def factorialAcc(acc: Int, n: Int): Int = {
      if (n <= 1) acc
      else factorialAcc(n * acc, n - 1)
    }
    factorialAcc(1, n)
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 对大数的阶乘有时会崩溃,有时不会 的相关文章

随机推荐