Bash 4.3+ - 递归斐波那契

时间:2017-06-15 18:04:42

标签: bash recursion fibonacci bash4

我正在编写我的编程语言,它编译成bash 4.3+代码。我处于语言的最后阶段,但我对递归函数有一个小问题。这是bash代码,它应该返回给定索引的fibnacci数。

#!/bin/bash

function fib() {
    local a=$1
    declare -n ret=$2
    if (( $a <= 2 )); then
        ret=1
        return
    fi
    fib $((a-1)) fib1
    fib $((a-2)) fib2

    ret=$((fib1+fib2))
    echo "fib($((a-1))) + fib($((a-2))) = $ret"
    return
}

num=5
fib $num result
echo 
echo "fib($num) = $result"

此代码中的问题是fib(5)给出3这显然是错误的。我认为问题是,当我传递fib1和fib2作为存储返回值的方法时,它们会被分配它们的每个调用覆盖。如果这是问题所在,我如何将fib1fib2置于执行范围内。

请注意,我不想使用return语句来返回值,我想尝试使用declare -n namerefs找到解决方案。

谢谢

1 个答案:

答案 0 :(得分:1)

  

我认为问题是,当我传递fib1和fib2作为存储返回值的方法时,它们会被分配它们的每个调用覆盖。

是的,您可以通过在递归调用之间和之后打印fib1的值来看到:

fib $((a-1)) fib1
echo "fib($a): fib1: $fib1"
fib $((a-2)) fib2
echo "fib($a): fib1: $fib1 fib2: $fib2"

您应该会在第二次通话中看到fib1的值发生变化。这是预期的,因为它没有被声明local并且只有一个fib1的全局副本。

如果你把它们当作本地......它没有多大帮助。

假设您首先致电fib 4 result。第一次迭代将使fib1为本地,并调用fib 3 fib1。现在第二次迭代也会使fib1为本地,但它也会尝试将其返回值赋给同名的变量。由于访问是按名称进行的,因此会将返回值保存到fib1自己的副本。

这可以通过一个稍微简单的脚本来看,它试图从递归的底部返回一个固定的值:

#!/bin/bash  
foo() {         
    declare -n ret=$2
    if (( $1 == 0 )); then
        echo "foo($1) returning"
        ret=end          # this is the value that should bubble up
        return
    fi
    local x=initial$1    # use $1 here to track the level the value came from
    foo $(($1 - 1)) x
    ret=$x
    echo "foo($1) = $x"
    return
}
foo 3 result
echo "main:    $result"

我能想到的解决方法是为返回值设置一个单独的全局变量,并立即将其复制到局部变量:

local fib1 fib2
fib $((a-1)) retval
fib1=$retval
fib $((a-2)) retval
fib2=$retval