/**
 * Exercise 4.4.1
 * The isGoodEnough test is not very precise for small numbers
 * and might lead to non-termination for very large ones (why?). Design a
 * different version of isGoodEnough which does not have these problems.
 *
 * OBS: in the book isGoodEnough is
 * def isGoodEnough(guess: Double, x: Double) =
 *   abs(square(guess) - x) < 0.001
 */

def sqrtIter(guess: Double, x: Double): Double =
  if (isGoodEnough(guess, x)) guess
  else sqrtIter(improve(guess, x), x)

def sqrt(x: Double) = sqrtIter(1.0, x)

println(sqrt(0.0001))
println(sqrt(9))
println(sqrt(1e308))

 

 

/**
 * Exercise 4.6.1 Design a tail-recursive version of factorial.
 */

def factorial(n: BigInt): BigInt = {
  def factLoop(accumulator: BigInt, i: BigInt): BigInt =
    if (i == 0 || i == 1)
      accumulator
    else
      factLoop(i * accumulator, i - 1)
  factLoop(1, n)
}


println("fat(5) = " + factorial(5))
println("fat(10) = " + factorial(10))
println("fat(100) = " + factorial(100))
println("fat(500) = " + factorial(500))