Рекурсивная функция в bash
Я хочу сделать функцию, которая вернет факториал числа в 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 = $?"
Ответы
Ответ 1
Существует несколько синтаксисов и довольно очевидная логическая (возврат 0)
Ниже приведена рабочая версия:
#!/bin/bash
factorial()
{
if [[ $1 -le 1 ]]
then
echo 1
else
last=$(factorial $[$1-1])
echo $(($1 * last))
fi
}
factorial 5
Вам не хватает:
Ответ 2
#!/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
echo
-из результата может быть единственный способ получить результат для n > 5, но для захвата результата echo'ed требуется подоболочка, что означает, что рекурсия будет дорого стоить. Более дешевое решение - использовать переменную:
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
Ответ 4
Другая реализация с использованием echo
вместо return
#!/bin/bash
factorial()
{
if [ $1 -le 1 ]
then
echo 1
else
echo $[ $1 * `factorial $[$1-1]` ]
fi
}
echo "factorial $1 = " `factorial $1`
Ответ 5
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