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.
<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.)
try this approach:
fn() {
echo 'returnValue';
}
echo `fn`;
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"
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
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.
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.