ふと思いたったので再帰呼び出ししてみる

…このタグつけるの何年ぶりだろう。…
なんてことはありません。いくつかの言語を使って、フィボナッチ数を求めるだけです。

1.Scheme

(define (fibo n)
 (define (fibo_inner n m k)
  (if (<= n 1) m
      (fibo_inner (- n 1) (+ m k) m)))
 (fibo_inner n 1 1))

(display (fibo 1000))(newline)

Cygwin上のguile(1.8.2)で実行した結果がこちら。

$ guile fibo.scm
7033036771142281582183525487718354977018126983635873274260490508715453711819693357974
2249494562611733487750449241765991088186363265450223647106012053374121273867339111198
139373125598767690091902245245323403501

Schemeは末尾最適化の実装を仕様で要求しているので、1000番目が10000番目でも計算できます。
あと、整数の大きさに制限がない(こちらの実装は「要求」ではなく、「奨励」らしい)ので、精確な値が見られます。(fibo 50000)とか、すごいことに。


2.TJS
吉里吉里スクリプト言語ですな。

function fibo(n)
{
    function fibo_inner(n, m, k)
    {
        if (n <= 1) return m;
        else {
            return fibo.fibo_inner(n - 1, m + k, m);
        }
    }

    return fibo_inner(n, 1, 1);
}

System.inform(fibo(1000), "fibo!");

安定版(2.28 stable rev.3)を使った結果はこちら。

スクリプトで例外が発生しました
EStackOverflow

エラーでした。再帰が深すぎて、スタックが溢れた?
ゲームの処理で、再帰を使うことなんてないから、大きな問題ではないのでしょう。

ちなみにエラーの回避法。

function fibo(n)
{
    var m = 1, k = 1, t = 0;

    while (n > 1) {
        t = m;
        m = m + k;
        k = t;

        n--;
    }

    return m;
}

末尾最適化を自分でやる(?)わけですな。
結果は、

9079565065540428013

Schemeと値が違うのは、桁あふれしたから?


3.Lua
なんとなく。

function fibo(n) 
    function fibo_inner(n, m, l) 
        if (n <= 0) then 
            return m 
        else 
            return fibo_inner(n - 1, m + l, m)
        end
    end

    return fibo_inner(n, 1, 1)
end

print(fibo(1000))

結果は(Cygwin+lua 5.1.2)、

$ lua fibo.lua
1.1379692539836e+209

…人生いろいろ?