Bash Script - Fibonacci

旧城冷巷雨未停 提交于 2019-12-02 06:54:14

问题


I was trying to make a recursive function that can calculate the Fibonacci of the enter number, by the way I got stuck on how to get the values obtained by the recursion.

#!/bin/bash

#Function - Fibonacci
fib()
{

  number=$1

  if (( number < 2 ))
    then
      (( tmp = number ))
  else
      ((--number))
      term1=$(fib $number)

      ((--number))
      term2=$(fib $number)

      (( tmp = $(( term1 + term2 )) )) #Problem is here

  fi

  (( result = $result + tmp ))
  return $result

}

#Main Program.
fib $1
  echo fib $1 = $?

Can someone help me?


回答1:


There are a couple of issues with your code. You cannot use $? for any useful arithmetic because the number wraps around at 255. And the embedded $((...)) is not useful at all -- you are already in arithmetic context inside the double parentheses.

#!/bin/bash

fib()
{
  local number term1 term2 # Avoid leaking to main scope
  number=$1
  if ((number < 2))
    then
      ((tmp=number))
  else
      ((--number))
      term1=$(fib "$number")
      ((--number))
      term2=$(fib "$number")
      ((tmp=term1+term2))
  fi
  ((result=result+tmp))
  printf '%s\n' "$result"
}

#Main Program.
fib "$1"   # Quote argument properly!

Inside the (( arithmetic parentheses )) you don't need the $ in front of variables; it's harmless, but you should probably try to be consistent.

As with any naïve Fibonacci implementation, this is hugely inefficient. It would be smarter to calculate the head of the sequence once in a helper function, then pull the final result and display it.

#!/bin/bash

fib2() {
    local f
    ((f=$1+$2))
    printf '%i %i\n' "$f" "$1"
}

fib()
{
    local i j
    j=$1
    shift
    for((i=1; i<j; ++i)); do
        set -- $(fib2 ${1-1} ${2-0})
    done
    printf '%s\n' "${1-$i}"
}

#Main Program.
fib "$1"



回答2:


I ran your code and I see that the numbers don't get returned when it is less than 2. It keeps decrementing the values and goes on to finding fibonacci of negative numbers. And probably that is the reason why it is giving strange results (this is after applying the fix given by Armali).

I am not sure if the syntax of these arithmetic operations are right as you have also pointed out in the line where you add results from the methods.

Check out this link which shows recursive function in bash but it prints the value rather than return. http://tldp.org/LDP/abs/html/recurnolocvar.html

What I understand is, there is some problem in the way the local variables are handled in bash recursive script. I see that when the function is calling the second time after the second decrement, the return value of the first call is over-writing the original number value leading to negative numbers and hence strange results. There must be some other way to handle return values in recursive calls.




回答3:


I do believe that you know "coding FIBONACCI with recursion is NOT a good idea".

recursive Fib() -> O(2^n)
iterative Fib() -> O(n)

Please reference to this youtube video.




回答4:


Re tripleee's answer: this can be done much faster still.

I think the helper function call is really expensive. Below version calculated fib 100000 at 2.344 seconds, whereas the helper-function version did the same at 1min 28.44 seconds. Although, you only get correct fibonacci up to like fib 92, at fib 93 for me you have hit the intmax_t setting.

fibnorec(){
    # typecheck                                                                                           
    if [[ ! "$1" =~ ^[0-9]+$ ]]
    then
        return 1
    fi

    # make arg into int                                                                                   
    declare -i n="$1"

    # Return fibonacci number at index n...                                                               
    if [[ $n -le 1 ]]
    then
        # index 0 and index 1 are numbers 0 and 1 respectively.
        printf '%s\n' $n;
    fi
    # For index 2 and up (position 3 and up)
    declare -i sum=1;
    declare -i prev=1;
    for ((i=2; i<n; i++))
    do
        declare -i save=$sum;
        sum+=$prev;
        prev=$save;
    done
    printf '%s\n' $sum
}
time fibnorec 100000



回答5:


try this approach:

fn() {
    echo 'returnValue';
}

echo `fn`;



回答6:


I got stuck on how to get the values obtained by the recursion.

You already have it right in the last line of your script - $?. Just do the same in fib - replace

      term1=$(fib $number)
      …
      term2=$(fib $number)

with

      fib $number; term1=$?
      …
      fib $number; term2=$?

Still your script returns strange values, but surely you can resume from here. (set -x might help.)



来源:https://stackoverflow.com/questions/29271910/bash-script-fibonacci

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!