我正在尝试使用递归函数来计算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
}
答案 0 :(得分:4)
这里有两个问题。首先,所有变量都是全局变量,这意味着当您进行递归调用时,它会覆盖nr
,rez
,rez1
和rez2
的值。您可以通过将其声明为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