Finding Fixed Points
满足f(x) = x的点就是所谓的Fixed Points,所以我们不断运用迭代使得误差小于阈值,最后得出我们想要的x
x => f(x) => f(f(x)) => …
val tolerance = 0.0001
def isCloseEnough(x: Double, y: Double) =
abs((x - y) / x) / x < tolerance
def fixedPoint(f: Double => Double)(firstGuess: Double) = {
def iterate(guess: Double): Double = {
val next = f(guess)
if (isCloseEnough(guess, next)) next
else iterate(next)
}
iterate(firstGuess)
}
fixedPoint(x => 1 + x / 2)(1)
以前求平方根的时候,我们用的是牛顿法,我们知道sqrt(x)的结果是满足y*y=x的y值,两边同除以y,sqrt(x)的结果是满足y=x/y的y值,所以就转换成求方程(y=> x/y)的fixed point
def sqrt(x: Double) =
fixedPoint(y => x / y)(1.0)
但是当我们运行sqrt(2)的时候发现函数并不收敛,而是不断地在1,2之间跳变,那么其中一种避免如此大跳变的方式就是对紧接着的值进行求平均
def sqrt(x: Double) =
fixedPoint(y => (y + x / y)/ 2)(1.0)
果然这样就成功收敛了。我们发现这方程就和牛顿法很相似了。为了进一步抽象集成,我们写出下面这个函数
def averageDamp(f: Double => Double)(x: Double) = (x + f(x)) / 2
最后我们结合fixedPoint和averageDamp完成平方根的求解
def sqrt(x: Double) = fixedPoint(averageDamp(y => x / y))(1)