Рекурсивная функция в bash - PullRequest
27 голосов
/ 13 марта 2012

Я хочу сделать функцию, которая будет возвращать факториал числа в bash

Вот текущий код, который не работает, может кто-нибудь сказать мне, что не так и как это исправить? Я только начал изучать bash и не очень много знаю.

#!/bash/bin
factorial()
{
  let n=$1
  if (( "$n" <= "1" ))
  then return 1
  else
  factorial n-1
  return $n*$?
  fi
  return 0
}
factorial 5
echo "factorial 5 = $?"

Ответы [ 5 ]

32 голосов
/ 13 марта 2012

Существует несколько синтаксисов и довольно очевидный логический (возвращаемый 0)

Рабочая версия ниже:

#!/bin/bash

factorial()
{
    if [[ $1 -le 1 ]]
    then
        echo 1
    else
        last=$(factorial $[$1-1])
        echo $(($1 * last))
    fi
}
factorial 5

Вы пропали без вести:

  1. если синтаксис плохой

  2. плохой рекурсивный вызов

  3. возврат плохой (там плохой синтаксис)

  4. строка shbang (is / bin / bash not / bash / bin)

17 голосов
/ 06 июня 2013
#!/bin/bash

function factorial() 
{ 
   if (( $1 < 2 ))
   then
     echo 1
   else
     echo $(( $1 * $(factorial $(( $1 - 1 ))) ))
   fi
}

Это будет работать лучше.

(В любом случае, он работает до 25, что должно быть достаточно, чтобы доказать смысл рекурсии.)

Для больших чисел bc будет инструментом для использования, сделав девятую строку выше:

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

но вы должны быть немного осторожнее с bc -

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

было очень тяжело для моей бедной системы!

3 голосов
/ 12 февраля 2016

echo - результат может быть единственным способом получить результат при n> 5, но для захвата отраженного результата требуется подоболочка, что означает, что рекурсия быстро станет дорогой.Более дешевое решение - использовать переменную:

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

Если вы хотите быть уверены, что val не установлена ​​при запуске, используйте функцию обтекания:

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

Длясравнение:

# 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
1 голос
/ 18 мая 2016
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
1 голос
/ 04 апреля 2014

Еще одна реализация, использующая echo вместо return

#!/bin/bash

factorial()
{
        if [ $1 -le 1 ]
        then
                echo 1
        else
                echo $[ $1 * `factorial $[$1-1]` ]
        fi
}
echo "factorial $1 = " `factorial $1`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...