简体   繁体   English

Fibonacci & for 循环:命令是如何一步一步执行的? (Bash shell 脚本)

[英]Fibonacci & for loop: how are the commands executed step by step? (Bash shell script)

I looked after many threads for my question, but didn't found the main answer.我为我的问题寻找了许多线索,但没有找到主要答案。 Here is a classic code written in bash:这是用 bash 编写的经典代码:

#!/bin/bash
a=0
b=1
echo "give a number:"
read n
clear
echo "the fibonacci sequence until $n:"
for (( i=0; i<n; i++ ))
do
  echo -n "$a "
  c=$((a + b))
  a=$b
  b=$c
done

If I interpret it well, this code echoes a $a value after every i++ jumps, then switches the variables as you can see, then on the next i++ loop jump it happens again until "i" reaches "n".如果我解释得很好,这段代码会在每次 i++ 跳转后回显一个 $a 值,然后如您所见切换变量,然后在下一个 i++ 循环跳转时再次发生,直到“i”到达“n”。 Question: if we want in every loop jump the value of the new "c" why shall we echo $a?问题:如果我们想在每个循环中跳转新的“c”的值,为什么我们要回显 $a? I see the connection that: a=$b, b=$c, and c=$((a + b)) but i don't get it why do we refer to $a when doing echo?我看到了这样的联系:a=$b, b=$c, and c=$((a + b)) 但我不明白为什么我们在做 echo 时要引用 $a ? Is there a more elegant solution?有没有更优雅的解决方案? Thank you for your respectful and in-depth analysis!感谢您的尊重和深入分析!

You mean, “never ever calculate anything needlessly, ever” ?你的意思是, “永远不要不必要地计算任何东西,永远” It is possible , of course, but it depends on how much ugliness in the control logic you are willing to tolerate.当然有可能,但这取决于您愿意容忍控制逻辑中的丑陋程度。 In the example below, fibonacci1 calculates at most one extra element of the series that may not get printed out and fibonacci2 never calculates any extra series elements and everything makes it to the standard output.在下面的例子中, fibonacci1最多计算一个可能不会被打印出来的序列的额外元素, fibonacci2永远不会计算任何额外的序列元素,并且一切都会进入标准输出。

Is any of that “elegant”?有这么“优雅”的吗? Probably not.可能不是。 This is actually a common problem most people encounter when coding (in languages other than purely functional ones): Most high(er)-level languages (unlike eg assemblers) provide predefined control structures that work great in typical and obvious cases (eg one control variable and one operation per iteration) but may become “suboptimal” in more complex scenarios.这实际上是大多数人在编码时遇到的常见问题(使用纯函数式语言以外的语言):大多数高级(更)级别的语言(与汇编程序不同)提供预定义的控制结构,这些结构在典型和明显的情况下(例如一个控制变量和每次迭代一个操作),但在更复杂的场景中可能会变得“次优”。

A notoriously common example is a variable that stores a value from the previous iteration.一个臭名昭著的常见示例是一个变量,它存储来自前一次迭代的值。 Let's assume you assign it at the very end of the loop.让我们假设您在循环的最后分配它。 That works fine, but… Could you avoid the very last assignment (because it is useless), instead of leaving it to the compiler's wisdom?这很好用,但是……你能避免最后一次赋值吗(因为它没用),而不是让编译器自行决定? Yes, you could , but then (eg) for ((init; condition; step)); do ...; ((previous = current)); done是的,你可以,但是(例如) for ((init; condition; step)); do ...; ((previous = current)); done for ((init; condition; step)); do ...; ((previous = current)); done for ((init; condition; step)); do ...; ((previous = current)); done becomes (eg) for ((init;;)); do ...; ((step)); ((condition)) || break; ((previous = current)); done for ((init; condition; step)); do ...; ((previous = current)); done变成了 (eg) for ((init;;)); do ...; ((step)); ((condition)) || break; ((previous = current)); done for ((init;;)); do ...; ((step)); ((condition)) || break; ((previous = current)); done for ((init;;)); do ...; ((step)); ((condition)) || break; ((previous = current)); done . for ((init;;)); do ...; ((step)); ((condition)) || break; ((previous = current)); done

On one hand, a tiny bit of something (such as thin air) may have been “saved”.一方面,一点点东西(例如稀薄的空气)可能已经“保存”了。 On the other hand, the code became assembler-like and harder to write, read and maintain.另一方面,代码变得像汇编程序一样,更难编写、阅读和维护。

To find a balance there^^^ and {not,} optimize when it {doesn't,does} matter is a lifelong struggle.在那里找到平衡^^^ 和{not,}在它{does't,does}重要时进行优化是一生的斗争。 It may be something like CDO, which is like OCD, but sorted correctly.它可能类似于 CDO,类似于 OCD,但排序正确。

fibonacci1() {
  local -ai fib=(0 1)
  local -i i
  for ((i = $1; i > 2; i -= 2)) {
    printf '%d %d ' "${fib[@]}"
    fib=($((fib[0] + fib[1])) $((fib[0] + 2 * fib[1])))
  }
  echo "${fib[@]::i}"
}

fibonacci2() {
  trap 'trap - return; echo' return
  local -ir n="$1"
  local -i a=0 b=1 i=0
  ((++i <= n)) || return 0
  printf '%d' "$a"
  ((++i <= n)) || return 0
  printf ' %d' "$b"
  for ((;;)); do
    ((++i <= n)) || return 0
    printf ' %d' "$((a += b))"
    ((++i <= n)) || return 0
    printf ' %d' "$((b += a))"
  done
}

for ((i = 0; i <= 30; ++i)); do
  for fibonacci in fibonacci{1,2}; do
    echo -n "${fibonacci}(${i}): "
    "$fibonacci" "$i"
  done
done

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM