实现这种算法的一种方法是这样的:
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函数计算平方根,但尝试通过
def sqrt(x: Double) = fixedPoint(y => x / y)(1)
因为这样的方法振荡(因此,对于sqrt(2),结果将无限期地在1.0和2.0之间交替).
为了解决这个问题,我们引入平均阻尼,因此基本上我们计算两个最接近的计算值的平均值并收敛到解
def sqrt(x: Double) = fixedPoint(y => (y + x / y) / 2)(1)
最后,我们介绍averageDamp函数,任务是使用fixedPoint和averageDamp写sqrt. averageDamp定义如下:
def averageDamp(f: Double => Double)(x: Double) = (x + f(x)) / 2
这是我不理解的部分 – 我最初的解决方案是:
def sqrt(x: Double) = fixedPoint(z => averageDamp(y => x / y)(z))(1)
教授.奥德斯基的解决方案更简洁:
def sqrt(x: Double) = fixedPoint(averageDamp(y => x / y))(1)
我的问题是 – 它为什么有效?根据函数签名,fixedPoint函数应该采用一个函数(Double => Double),但它不介意传递普通的Double(这是averageDamp返回的 – 事实上,如果你试图明确指定返回double to averageDamp的类型,编译器不会抛出错误).
我认为我的方法正确地遵循了类型 – 所以我在这里缺少什么?它指定或暗示(?)meanDamp返回一个函数,特别是在右边显然返回一个标量的情况下?如何将标量传递给仅明确需要函数的函数?你怎么推理似乎不尊重类型签名的代码?
解决方法
让我们更仔细地检查averageDamp函数.
def averageDamp(f: Double => Double)(x: Double): Double = (x + f(x)) / 2
添加返回类型注释以使其更清晰.我想你缺少的是:
but it doesn’t mind being passed an ordinary Double (which is what averageDamp returns – in fact,if you try to explicitly specify the
return type of Double to averageDamp,the compiler won’t throw an
error).
但是averageDamp(y => y / x)确实返回Double =>双重功能! averageDamp需要传递两个参数列表才能返回Double.
如果函数只接收一个参数,它仍然希望完成另一个参数.因此,不是立即返回结果,而是返回一个函数,说“我仍然需要一个参数,喂我,所以我会返回你想要的”.
MO教授确实向它传递了一个函数参数,而不是两个,所以averageDamp被部分应用,因为它返回一个Double =>双重功能.
该课程还将告诉您多个参数列表的函数是这种语法糖形式:
def f(arg1)(arg2)(arg3)...(argN-1)(argN) = (argN) => f(arg1)(arg2)(arg3)...(argN-1)
如果你给出一个少于f需要的参数,它只返回方程的右边,即一个函数.因此,注意averageDamp(y => x / y),传递给fixPoint的参数实际上是一个函数应该可以帮助您理解这个问题.
注意:部分应用函数(或函数currying)与多参数列表函数之间存在一些差异
例如,你不能这样声明
val a = averageDamp(y => y/2)
这里解释了不同之处:What’s the difference between multiple parameters lists and multiple parameters per list in Scala?.