15.08.2013 Views

General Computer Science 320201 GenCS I & II Lecture ... - Kwarc

General Computer Science 320201 GenCS I & II Lecture ... - Kwarc

General Computer Science 320201 GenCS I & II Lecture ... - Kwarc

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

generally: fn+1 := fn + fn−1 plus start conditions<br />

easy to program in SML:<br />

fun fib (0) = 0 |fib (1) = 1 | fib (n:int) = fib (n-1) + fib(n-2);<br />

Let us look at the recursion relation: {〈n, n − 1〉, 〈n, n − 2〉 | n ∈ N} (it is a tree!)<br />

4<br />

3 2<br />

2 1 1 0<br />

1 0<br />

6<br />

5 4<br />

3<br />

3 2<br />

2 1 2 1 1 0<br />

1 0 1 0<br />

c○: Michael Kohlhase 106<br />

Another thing we see by looking at the recursion relation is that the value fib(k) is computed<br />

n−k+1 times while computing fib(k). All in all the number of recursive calls will be exponential<br />

in n, in other words, we can only compute a very limited initial portion of the Fibonacci sequence<br />

(the first 41 numbers) before we run out of time.<br />

The main problem in this is that we need to know the last two Fibonacci numbers to compute<br />

the next one. Since we cannot “remember” any values in functional programming we take<br />

advantage of the fact that functions can return pairs of numbers as values: We define an auxiliary<br />

function fob (for lack of a better name) does all the work (recursively), and define the function<br />

fib(n) as the first element of the pair fob(n).<br />

The function fob(n) itself is a simple recursive procedure with one! recursive call that returns<br />

the last two values. Therefore, we use a let expression, where we place the recursive call in the<br />

declaration part, so that we can bind the local variables a and b to the last two Fibonacci numbers.<br />

That makes the return value very simple, it is the pair (b,a+b).<br />

A better Fibonacci Function<br />

Idea: Do not re-compute the values again and again!<br />

keep them around so that we can re-use them.<br />

(e.g. let fib compute the two last two numbers)<br />

fun fob 0 = (0,1)<br />

| fob 1 = (1,1)<br />

| fob (n:int) =<br />

let<br />

val (a:int, b:int) = fob(n-1)<br />

in<br />

(b,a+b)<br />

end;<br />

fun fib (n) = let val (b:int,_) = fob(n) in b end;<br />

Works in linear time! (unfortunately, we cannot see it, because SML Int are too small)<br />

c○: Michael Kohlhase 107<br />

If we run this function, we see that it is indeed much faster than the last implementation. Unfortunately,<br />

we can still only compute the first 44 Fibonacci numbers, as they grow too fast, and we<br />

reach the maximal integer in SML.<br />

Fortunately, we are not stuck with the built-in integers in SML; we can make use of more<br />

sophisticated implementations of integers. In this particular example, we will use the module<br />

58

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!