仅使用1个变量在bash中使用递归打印Fibonacci系列

时间:2019-02-26 14:32:21

标签: bash recursion fibonacci

我想知道如何使用bash中只有1个变量的递归来打印斐波那契数列。

从我所做的事情来看:

fib()
    {
    i=$1
    if (( $i <= 1 ))
    then echo 0
    elif (( $i == 2 ))
    then echo 1
    else

    echo $(( $(fib $(($i - 1)) ) + $(fib $(($i - 2)) ) ))

fi
 }

echo $(fib $1)

我得到了最终迭代的正确输出,例如,如果输入10,我将得到34,但是我想打印整个数字序列,即所有迭代。我该如何实现?

我尝试的另一种方法是:

#!/bin/bash
arr[0]=0
arr[1]=1

for (( i=0; i<=10; i++ ))
do
    echo -n "${arr[0]} "
    arr[0]=$((${arr[0]} + ${arr[1]} ))
    arr[1]=$((${arr[0]} - ${arr[1]} ))
done
echo ""

但是很明显,我在这里使用了for循环,但是我不想使用另一个变量。

3 个答案:

答案 0 :(得分:3)

bash中的变量默认为全局变量。您需要明确地将i设为本地。

 fib () {
     local i
     i=$1
     if (( i <= 1 )); then
         echo $i
     else
         echo $(( $(fib $((i-1)) ) + $(fib $((i - 2)) ) ))
     fi
}

(此外,如果您从0开始,您的基本情况就有些差了,而2不必是基本情况; fib 2可以从基本情况fib 0和{{1 }}。

答案 1 :(得分:3)

只是出于(我的一种)乐趣,此代码使用不使用变量的递归函数将斐波那契数从0排到第92(按Fibonacci number - Wikipedia的定义):

#! /bin/bash

function fib
{
    echo ${3-0}

    (($1 > 0)) && fib $(($1-1)) ${3-0} $((${2-1}+${3-0}))
}

fib 92

有人可能会说使用位置参数($1$2$3)是作弊行为,但是其他解决方案可以说是使用两个变量({{ 1}}和$i)。

在我(旧的)Linux计算机上运行该代码需要不到0.01秒的时间。

在任何平台上的Bash版本3或更高版本中,代码都可以使用最大为92的数字。参见Bash Number Limit?。大于93的数字会由于算术溢出而导致代码产生垃圾结果。

答案 2 :(得分:1)

如果要将每个斐波那契值从1打印到$ n,我建议:

fib_r() {
    local i=$1
    if (( i < 0 )); then
        echo "Error: negative numbers not allowed" >&2
        exit 1

    elif (( i <= 1 )); then
        echo $i

    else
        echo $(( $($FUNCNAME $((i - 1)) ) + $($FUNCNAME $((i - 2)) ) ))
    fi
}

fib() {
    local i
    for (( i = 1; i <= $1; i++ )); do
        fib_r $i
    done
}

fib 10

输出

0
1
1
2
3
5
8
13
21
34

它仍然是一个变量,尽管每个函数一个。

我在递归函数中使用bash变量$ FUNCNAME,因此您不必在内部使用硬编码函数名。重命名该函数时,我没有更新该行。


当然,如果您缓存结果,您的性能将会大大提高:“ fib 16”在我的VM上大约需要3.5秒而不进行缓存,而大约需要0.03秒。

fib_r() {
    local i=$1
    if (( i < 0 )); then
        echo "Error: negative numbers not allowed" >&2
        exit 1

    elif [[ -n ${fib_cache[i]} ]]; then
        echo "${fib_cache[i]}"

    elif (( i <= 1 )); then
        echo $i

    else
        echo $(( $( $FUNCNAME $((i - 1)) ) + $( $FUNCNAME $((i - 2)) ) ))
    fi
}

fib_cache=()

fib() {
    local i
    for ((i=1; i<=$1; i++)); do
        fib_cache[i]=$(fib_r $i)
        echo "${fib_cache[i]}"
    done
}