许多数字问题的形式如下:
initialize: x_0 = ...
iterate: x_i+1 = function(x_i) until convergence, e.g.,
|| x_i+1 - x_i || < epsilon
我想知道是否有一种很好的方法来使用惯用的Scala编写这样的算法。问题的性质需要Iterator
或Stream
。但是,我目前对此的看法看起来很丑陋:
val xFinal = Iterator.iterate(xInit) { x_i =>
// update x_i+1
}.toList // necessary to pattern match within takeWhile
.sliding(2) // necessary since takeWhile needs pair-wise comparison
.takeWhile{ case x_i :: x_iPlus1 :: Nil => /* convergence condition */ }
.toList // since the outer container is still an Iterator
.last // to get the last element of the iteration
.last // to get x_iPlus1
这不仅很难看,takeWhile
中的模式匹配也会引起警告。显然我不需要在这里进行模式匹配,但我希望与数学原型保持强烈的相似性。
任何想让它看起来更漂亮的想法?
答案 0 :(得分:1)
以下极简主义(愚蠢)的例子可能会说明一个有用的框架,
def function (i:Int): Int = i+1
def iter (x0: Int): Int = {
val x1 = function(x0)
if (x1 - x0 == 1) x1 else iter(x1)
}
答案 1 :(得分:1)
这是我使用牛顿方法找到平方根的例子的解决方案,在这种情况下减少了巴比伦方法:
import math.abs
val tol=0.00001
val desiredSqRoot=256
val xFinal = Iterator.iterate(1.0) { x => 0.5*(x+desiredSqRoot/x) }
def converged(l: Seq[Double]): Boolean = l match{
case x_old :: x_new :: Nil => if( abs(x_old-x_new)/x_old < tol ) true else false
case _ => true
}
xFinal.sliding(2).dropWhile( x=> !converged(x) ).next.last
结果为:
scala> xFinal.sliding(2).dropWhile( x=> !converged(x) ).next.last
res23: Double = 16.00000000000039
在这个例子中,我们知道它应该收敛的值,但是我在没有这方面知识的情况下编写了收敛标准,因为通常我们不知道这一点。