我的变量赋值有什么问题?

What's wrong with my variable assignment?

提问人:ToegapBananaboat 提问时间:11/14/2023 更新时间:11/14/2023 访问量:59

问:

我正在尝试编写一个斐波那契函数,该函数将输入 int 作为序列的长度。这是我的代码:

function fib {
        local len=$1
        echo "len = $len"

        local arr=(0 1 1)

        if [[ $len -le 3 ]]
        then
                echo ${arr[@]:0:$len}
                let arr=${arr[@]:0:$len}
                echo $arr
        else
                while [[ ${#arr[*]} -lt $len ]]
                do
                        local sum=${arr[${#arr[*]}]}+${arr[${#arr[*]}-1]}
                        let arr+=$sum
                        echo "curren len = ${#arr[*]}"
                done
        fi

        echo "arr = $arr"
}

这是我调用函数时得到的结果:

👉👉👉 fib 2
len = 2
0 1
0
arr = 0
👉👉👉 fib 3
len = 3
0 1 1
0
arr = 0

请忽略它现在是否有效。为什么我在简单地回声时会得到正确的顺序?但不是当我?let arr=

bash unix 变量赋值 斐波那契

评论

0赞 teapot418 11/14/2023
尝试在循环中回显计算出的总和附加的 arr。他们是你所期望的吗?
3赞 teapot418 11/14/2023
我认为追加应该是(没有)。我将把调试总和留给你,arr+=($sum)let
0赞 ToegapBananaboat 11/14/2023
啊,谢谢!@teapot418我忘了使用数组括号!!但是我什么时候需要使用呢?let
2赞 teapot418 11/14/2023
let用于计算算术表达式。当只是附加时,你真的不希望这样。计算总和可能应该是 1。
2赞 glenn jackman 11/14/2023
Shellcheck 建议不要让 expr,而是首选 (( expr ))。

答:

3赞 Andrej Podzimek 11/14/2023 #1

您需要通读 中关于扩展的冗长而无聊的章节,其中显示了如何使用数组。 将数组的值扩展为单独的标记。 将数组的索引(或键)扩展为单独的标记。使用 instead 会生成一个字符串,该字符串由 中的第一个字符分隔。将数组变量扩展为标量 () 会产生 ,它可能存在也可能不存在,因为索引数组是稀疏的,可能不包含元素,而关联数组可能包含也可能不包含键。下面的代码片段还显示了 Bash 提供的漂亮的“调试”扩展。(查找 .)man bash"${array[@]}""${!array[@]}"*@$IFS"$array""${array[0]}"[0]['0']@A

generate_fibonacci_sequence() {
  local -i counter="$1"
  local -n _output_array="$2"  # declare -ai
  _output_array=()
  ((counter)) || return 0
  local -i a=0 b=1
  for ((;;)); do
    _output_array+=(a)
    ((--counter)) || return 0
    ((b += a))
    _output_array+=(b)
    ((--counter)) || return 0
    ((a += b))
  done
}

declare -ai sequence

for length in {0..20}; do
  generate_fibonacci_sequence "$length" 'sequence'
  printf '%s\n%s %s %s\n' "${length@A}" "${sequence[@]@A}"
  printf '['
  for i in "${!sequence[@]}"; do
    printf '(%d:%d)' "$i" "${sequence[i]}"
  done
  printf ']\n\n'
done

输出的开头:

length='0'
declare -ai sequence=()
[]

length='1'
declare -ai sequence=([0]="0")
[(0:0)]

length='2'
declare -ai sequence=([0]="0" [1]="1")
[(0:0)(1:1)]

length='3'
declare -ai sequence=([0]="0" [1]="1" [2]="1")
[(0:0)(1:1)(2:1)]

length='4'
declare -ai sequence=([0]="0" [1]="1" [2]="1" [3]="2")
[(0:0)(1:1)(2:1)(3:2)]

length='5'
declare -ai sequence=([0]="0" [1]="1" [2]="1" [3]="2" [4]="3")
[(0:0)(1:1)(2:1)(3:2)(4:3)]

length='6'
declare -ai sequence=([0]="0" [1]="1" [2]="1" [3]="2" [4]="3" [5]="5")
[(0:0)(1:1)(2:1)(3:2)(4:3)(5:5)]

length='7'
declare -ai sequence=([0]="0" [1]="1" [2]="1" [3]="2" [4]="3" [5]="5" [6]="8")
[(0:0)(1:1)(2:1)(3:2)(4:3)(5:5)(6:8)]

...

无论如何,请注意,Bash 在后台使用有符号的 64 位整数,其下溢/溢出行为在(例如)C++ 中被视为未定义

$ echo $((2**63))
-9223372036854775808
$ echo $((2**63 - 1))
9223372036854775807

话虽如此,在 Python 中计算大斐波那契数可能会更好,Python 在后台使用 GNU MP。(或者直接使用 GNU MP。