Recursive function in bash

后端 未结 6 1647
渐次进展
渐次进展 2020-12-13 09:33

I want to do a function that will return the factorial of a number in bash

Here\'s the current code that doesn\'t work, can anyone tell me what\'s wrong and how to c

相关标签:
6条回答
  • 2020-12-13 10:12
    #!/bin/bash
    
    function factorial() 
    { 
       if (( $1 < 2 ))
       then
         echo 1
       else
         echo $(( $1 * $(factorial $(( $1 - 1 ))) ))
       fi
    }
    

    This will work better.

    (It works up to 25, anyway, which should be enough to prove the point about recursion.)

    For higher numbers, bc would be the tool to use, making the ninth line above:

    echo "$1 * $(factorial $(( $1 - 1 )))" | bc
    

    but you have to be a bit careful with bc --

    $ factorial 260
    38301958608361692351174979856044918752795567523090969601913008174806\
    51475135399533485285838275429773913773383359294010103333339344249624\
    06009974551133984962615380298039823284896547262282019684886083204957\
    95233137023276627601257325925519566220247124751398891221069403193240\
    41688318583612166708334763727216738353107304842707002261430265483385\
    20637683911007815690066342722080690052836580858013635214371395680329\
    58941156051513954932674117091883540235576934400000000000000000000000\
    00000000000000000000000000000000000000000
    

    was quite a strain on my poor system!

    0 讨论(0)
  • 2020-12-13 10:16

    Another one implementation using echo instead of return

    #!/bin/bash
    
    factorial()
    {
            if [ $1 -le 1 ]
            then
                    echo 1
            else
                    echo $[ $1 * `factorial $[$1-1]` ]
            fi
    }
    echo "factorial $1 = " `factorial $1`
    
    0 讨论(0)
  • 2020-12-13 10:20

    echo-ing a result may be the only way to get a result for n > 5, but capturing the echo'ed result requires a subshell, which means the recursion will get expensive fast. A cheaper solution is to use a variable:

    factorial() {
        local -i val=${val:-($1)}
        if (( $1 <= 1 )); then
            echo $val
            return
        fi
        (( val *= $1 - 1 ))
        factorial $(( $1 - 1 ))
    }
    

    If you want to be extra sure that val is unset when you start, use a wrapping function:

    factorial() {
        local -i val=$1
        _fact() {
            if (( $1 <= 1 )); then
                echo $val
                return
            fi
            (( val *= $1 - 1 ))
            _fact $(( $1 - 1 ))
        }
        _fact $1
    }
    

    For comparison:

    # My Method
    $ time for i in {0..100}; do factorial $(( RANDOM % 21 )); done > /dev/null 
    
    real    0m0.028s
    user    0m0.026s
    sys     0m0.001s
    
    # A capturing-expression solution
    $ time for i in {0..100}; do factorial $(( RANDOM % 21 )); done > /dev/null 
    
    real    0m0.652s
    user    0m0.221s
    sys     0m0.400s
    
    0 讨论(0)
  • 2020-12-13 10:26

    There are several syntax and a quite obvious logic one (return 0)

    A working version is below:

    #!/bin/bash
    
    factorial()
    {
        if (( $1 <= 1 )); then
            echo 1
        else
            last=$(factorial $(( $1 - 1 )))
            echo $(( $1 * last ))
        fi
    }
    factorial 5
    

    You are missing:

    1. return is bad (should use echo)

    2. shbang line (is /bin/bash not /bash/bin)

    3. Can't do arithmetic outside of (( )) or $(( )) (or let, but (( )) is preferred)

    0 讨论(0)
  • 2020-12-13 10:27
    clear cat
    
    fact()
    
    {
    
            i=$1
            if [ $i -eq 0 -o $i -eq 1 ]
            then
                    echo 1
            else
                    f=`expr $i \- 1`
                    f=$(fact $f)
                    f=`expr $i \* $f`
                    echo $f
            fi
    }
    
    read -p "Enter the number : " n
    
    if [ $n -lt 0 ]
    
    then
    
            echo "ERROR"
    
    else
    
            echo "THE FACTORIAL OF $n : $(fact $n) "
    fi
    
    0 讨论(0)
  • 2020-12-13 10:27
    #-----------------factorial ------------------------
    # using eval to avoid process creation
    fac=25
    factorial()
    {
        if [[ $1 -le 1 ]]
        then
            eval $2=1
        else
    
            factorial $[$1-1] $2
            typeset f2
            eval f2=\$$2
            ((f2=f2*$1))
            eval $2=$f2
    
        fi
    }
    time factorial $fac res 
    echo "factorial =$res"
    
    0 讨论(0)
提交回复
热议问题