Shell脚本生成Fibonacci系列

时间:2017-03-23 21:46:01

标签: bash

我正在尝试使用递归函数来计算Fibonnaci系列的第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
}

2 个答案:

答案 0 :(得分:4)

这里有两个问题。首先,所有变量都是全局变量,这意味着当您进行递归调用时,它会覆盖nrrezrez1rez2的值。您可以通过将其声明为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版本):< / p>

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

第14个Fibonacci数字是377,但是超过255,所以它出现了377-256 = 121.要解决这个问题,请将结果echo返回到stdout并使用$( )

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

...这确实有一个缺点:它要慢得多,因为每次调用fib都必须作为子进程运行,而创建子进程的计算成本很高。 (这实际上会解决全局变量问题,因为变量会继承到子进程但不会从它们中继承;但它只会偶然解决它。)

带回家的教训:shell脚本不适合这样的语言。

答案 1 :(得分:1)

awk

等方式更容易
$ 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