web-dev-qa-db-ja.com

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 = $?"
28
FinalDestiny

いくつかの構文と非常に明白な論理があります(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行(/ bash/binではなく/ bin/bash)

34
Daniel Voina
#!/bin/bash

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

これはうまく機能します。

(とにかく最大25まで動作し、再帰についてのポイントを証明するのに十分なはずです。)

数値が大きい場合、bcが使用するツールとなり、上記の9行目が作成されます。

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

しかし、bcには少し注意する必要があります-

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

私の貧弱なシステムに大きな負担をかけました!

17
user1070300

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
3
kojiro

echoの代わりにreturnを使用する別の実装

#!/bin/bash

factorial()
{
        if [ $1 -le 1 ]
        then
                echo 1
        else
                echo $[ $1 * `factorial $[$1-1]` ]
        fi
}
echo "factorial $1 = " `factorial $1`
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
Sayan Roy Subho