Подтвердить что ты не робот

Рекурсивная функция в 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 = $?"
4b9b3361

Ответ 1

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

Ниже приведена рабочая версия:

#!/bin/bash

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

Вам не хватает:

  • Если синтаксис плох

  • Рекурсивный вызов плох

  • return is bad (плохой синтаксис eval)

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

Ответ 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