2017-03-23 4 views
2

フィボナッチシリーズからn番目の数値を計算するための再帰関数を作成しようとしています。私はすでにこの問題の解決策をたくさん見つけていますが、なぜ私が働かないのかを知るためには何が必要ですか。ありがとう。フィボナッチシリーズを生成するシェルスクリプト

function fib() 
{ 
     if [ $1 -eq 1 -o $1 -eq 2 ] 
     then 
       return 1 
     else 
       let nr=$1-1 
       fib $nr 
       rez1=$? 
       let nr=$1-2 
       fib $nr 
       rez2=$? 
       let rez=$rez1+$rez2 
       return $rez 
     fi 
} 
+0

関連:http://stackoverflow.com/q/17336915/632407 – jm666

答えて

4

ここには2つの問題があります。まず、すべての変数はグローバルです。つまり、再帰呼び出しを行うと、nr,rez,rez1rez2という値が上書きされます。あなたはlocalとしてそれらを宣言することでこの問題を解決することができます

fib() { 
    local nr rez rez1 rez2 
    if [ $1 -eq 1 -o $1 -eq 2 ]; then 
     return 1 
    else 
     let nr=$1-1 
     fib $nr 
     rez1=$? 
     let nr=$1-2 
     fib $nr 
     rez2=$? 
     let rez=$rez1+$rez2 
     return $rez 
    fi 
} 

第二の問題は、あなたが関数の戻り値の状態を経由して番号を渡すためにしようとしているということです。戻りステータスは、1バイトの符号なし整数です。つまり、255より大きくなることはできません(その後、0にラップアラウンドします)。実際に成功/失敗の結果(何が失敗したかについての情報)を与えることを意図しています。 。0何か他のものは、トラブルを求めているためにそれを使用しようとするとエラーを示す成功と何かを示すあなたは(機能のlocal化さバージョンから)ここでの結果を見ることができます:。

$ fib 11; echo $? 
89 
$ fib 12; echo $? 
144 
$ fib 13; echo $? 
233 
$ fib 14; echo $? 
121 

14日フィボナッチ数377ですが、それは255を超えていますので、377-256 = 121として出てきました。これを修正するには、echoで結果を返し、$()

...しかし、これは非常に遅いです。fibへのすべての呼び出しはサブプロセスとして実行する必要があり、サブプロセスを作成するには計算コストがかかるためです。 (これは実際には変数がサブプロセスに継承されるが、それらからは継承されないため、グローバル変数問題は解決されていますが、偶然にのみ解決されます)

Take-homeレッスン:シェルスクリプトは正しくありませんこのようなことのための言語。

それは awkのようなもので道に簡単です
1

$ echo 11 | awk 'function fib(n) { 
    return n<2 ? n : fib(n-1) + fib(n-2) 
} $1+0>0 {print fib($1)}' 
89 

$ echo 35 | awk 'function fib(n) { 
    return n<2 ? n : fib(n-1) + fib(n-2) 
} $1+0>0 {print fib($1)}' 
9227465 

それとも、あなたはカンマ区切りの数字をしたい場合:

$ echo 39 | awk 'function fib(n) { 
    return n<2 ? n : fib(n-1) + fib(n-2) 
} $1+0>0 {printf ("%'"'"'d\n", fib($1))}' 
63,245,986 
関連する問題