1

I had looked on overflow and exchange, but I can't seem to find an answer for this. I am currently trying to make a recursive fibonacci function. However when I try to test it (using command line entry) it keeps returning the error

fork: retry: Resource temporarily unavailable

I had found a post saying it had to do with shell resource limits, but I felt like that probably wasn't my issue since I've seen separate posts with recursive functions being able to call their function fine enough.

I had broken up the operation into parts to see what exactly was happening, but I can't find a specific problem - it may have to do with how i'm calling my function, but I'm not sure, either.

I can pass the parameter I want just fine, though. It just prints the same error for whatever number I put in. If I enter 5, it echoes the fork error five times. It returns, but doesn't return the values...

For specification, I currently use Bash Version 4.4.20(1)

function fib_r
{
    int=$1

    for ((i=1; i<=int; i++))
    do

    f1=$(fib_r $((int-1)))
    f2=$(fib_r $((int-2)))
    fibo=$((f1+f2))

    done
}

What I want to achieve is when you enter a number on command line, It does calculate that number, however it shows the calculated number at each step, rather than return the final value from start to end:

An example output:

1          1
2          1
3          2
4          3
5          5
6          8
7          13
8          21
9          34
10         55
wegmans
  • 13
  • 3
  • One of your previous tries is probably running wild in the background, launching an infinite amount of forks. You should reboot the computer (killing the processes is also possible but it's difficult to help you with that from here). BTW, is it mandatory for you to write a recursive function? an iterative one would be incomparatively more performant. – Fravadona May 13 '22 at 11:21
  • For this assignment, yes. My professor wants us to make a bash script that includes recursion for timing purposes – wegmans May 13 '22 at 18:09

1 Answers1

2

This Shellcheck-clean code fixes a few problems with the code in the question:

function fib_r
{
    local -r n=$1

    if (( n == 0 )); then
        echo 0
    elif (( n == 1 )); then
        echo 1
    else
        local -r f1=$(fib_r "$((n-1))")
        local -r f2=$(fib_r "$((n-2))")
        echo "$((f1+f2))"
    fi

    return 0
}
  • It adds code for base cases (0 and 1) to stop the recursion. The original code had no base cases so the recursion continued until resources were exhausted.
  • The function echos the result so it is available to the caller. Command substitution ($(command)) is usually only useful if the command prints its result(s) to standard output.
  • The loop was removed because this is supposed to be a recursive function (and the loop wasn't useful).
  • local is used to make variables local to the function so they won't clash with variables used elsewhere in a program that uses the function. The -r (readonly) option is used because the variables never need to be changed within the function and it prevents them being accidentally changed by other functions.
  • The variable name int was changed to n because that is more conventional for functions like this (and int seems really strange to people who know C, or related programming languages).

Note that this function is very slow. That is partly because it uses command substitution (which runs an expensive sub-process every time) to return results, but mostly because this particular recursive algorithm is very inefficient (exponential complexity, see Computational complexity of Fibonacci Sequence). Much faster recursive implementations are possible.

The question was updated to request a function that prints all of the Fibonacci numbers up to a given number. This is a recursive function that does that:

function fib_r
{
    local -r n=$1
    local -r depth=${2-1}
    local -r f1=${3-1}
    local -r f2=${4-0}

    if (( depth <= n )); then
        printf '%2d  %d\n' "$depth" "$f1"
        fib_r "$n" "$((depth+1))" "$((f1+f2))" "$f1"
    fi

    return 0
}

This uses a much more efficient algorithm (O(n)), so it can calculate all of the Fibonacci numbers that can be represented by a 64-bit integer in a fraction of a second. Run fib_r 92 to do that.

pjh
  • 6,388
  • 2
  • 16
  • 17
  • @M.NejatAydin, thanks for pointing out my careless mistake. I've updated my answer. – pjh May 13 '22 at 13:16
  • Thank you for your help on this - I appreciate it - Though for some reason it keeps returning the calculated number, rather than the number at each step...is that supposed to happen? i.e. ```1 is 1, 2 is 1, 3 is 2...``` it just skips to the calculated number based on an input number. so when I enter 10, it gives back 55 and only 55. I apologize for not including this in my post - i'll update it accordingly – wegmans May 13 '22 at 18:19
  • @wegmans you first define the recursive function then you call it in a loop: `for ((i=0;i<=10;i++)); do fib_r "$i"; done`; doing all of it directly inside the function kills the recursion. – Fravadona May 13 '22 at 18:47
  • @wegmans, I've added a new recursive function that does what you requested in your updated question. – pjh May 13 '22 at 23:07
  • @pjh thanks for you help on this - i appreciate this – wegmans May 14 '22 at 02:54