if-else
写一个函数使得所有的表达式都满足:
and(x,y) == x && y
or(x,y) == x || y
但是不能使用&&和||。
def and(x:Boolean, y: => Boolean) = if (x) y else false
def or(x:Boolean, y: => Boolean) = if (x) true else y
定义函数-采用牛顿法计算平方根
def abs(x: Double) = if (x < 0) -x else x //> abs: (x: Double)Double
def sqrtIter(guess: Double, x: Double): Double =
if (isGoodEnough(guess, x)) guess
else sqrtIter(improve(guess, x), x) //> sqrtIter: (guess: Double, x: Double)Double
def isGoodEnough(guess: Double, x: Double) =
abs(guess * guess - x) < 1e-3 //> isGoodEnough: (guess: Double, x: Double)Boolean
def improve(guess: Double, x: Double) =
(guess + x / guess) / 2 //> improve: (guess: Double, x: Double)Double
def sqrt(x: Double) = sqrtIter(1.0, x) //> sqrt: (x: Double)Double
sqrt(2) //> res0: Double = 1.4142156862745097
sqrt(9) //> res1: Double = 3.00009155413138
sqrt(1e-20) //> res2: Double = 0.03125
/
sqrt(1e50)
从eclipse的编译结果来看,当x特别小的时候,计算结果不准确;当x特别大的时候,无法计算出结果,陷入循环。
原因很简单,当x太小时,0.001的阈值就会太高,达不到精度,迭代就停止了,所以不准确。当x太大时,0.001的阈值太低,需要迭代非常多(无尽)的次数才能停止,所以陷入循环。做如下修改就能完美的hold住这两种情况
def abs(x: Double) = if (x < 0) -x else x //> abs: (x: Double)Double
def sqrtIter(guess: Double, x: Double): Double =
if (isGoodEnough(guess, x)) guess
else sqrtIter(improve(guess, x), x) //> sqrtIter: (guess: Double, x: Double)Double
def isGoodEnough(guess: Double, x: Double) =
abs(guess * guess - x) < x * 1e-3 //> isGoodEnough: (guess: Double, x: Double)Boolean
def improve(guess: Double, x: Double) =
(guess + x / guess) / 2 //> improve: (guess: Double, x: Double)Double
def sqrt(x: Double) = sqrtIter(1.0, x) //> sqrt: (x: Double)Double
sqrt(2) //> res1: Double = 1.4142156862745097
sqrt(9) //> res2: Double = 3.00009155413138
sqrt(1e-20) //> res3: Double = 1.0000021484861236E-10
sqrt(1e50) //> res4: Double = 1.0000003807575104E25
分块和词领域
avoid “name-space” pollution
def sqrt(x: Double) = {
def sqrtIter(guess: Double, x: Double): Double =
if (isGoodEnough(guess, x)) guess
else sqrtIter(improve(guess, x), x) //> sqrtIter: (guess: Double, x: Double)Double
def isGoodEnough(guess: Double, x: Double) =
abs(guess * guess - x) < x * 1e-3 //> isGoodEnough: (guess: Double, x: Double)Boolean
def improve(guess: Double, x: Double) =
(guess + x / guess) / 2 //> improve: (guess: Double, x: Double)Double
sqrtIter(1.0, x) //> sqrt: (x: Double)Double
}
定义在块里的参数,只在块里可见,定义在外面的参数,块里块外都可见,除非块里重复定义了该参数将参数覆盖掉。
由于x在整个块内都是可见的,于是我们可以简化我们的代码,让它看起来更舒服,整洁,减少代码上的冗余。
def sqrt(x: Double) = {
def sqrtIter(guess: Double): Double =
if (isGoodEnough(guess)) guess
else sqrtIter(improve(guess))
def isGoodEnough(guess: Double) =
abs(guess * guess - x) < x * 1e-3
def improve(guess: Double) =
(guess + x / guess) / 2
sqrtIter(1.0)
}