私は夢中になっています:階乗のRuby関数はどこにありますか?いいえ、チュートリアルの実装は必要ありません。ライブラリの関数が必要なだけです。それは数学ではありません!
私は疑問を持ち始めています、それは標準ライブラリ関数ですか?
私は夢中になっています:階乗のRuby関数はどこにありますか?いいえ、チュートリアルの実装は必要ありません。ライブラリの関数が必要なだけです。それは数学ではありません!
私は疑問を持ち始めています、それは標準ライブラリ関数ですか?
(1..6).inject(:*)
、もう少し簡潔です。
(1..num).inject(:*)
の場合は失敗しますnum == 0
。(1..(num.zero? ? 1 : num)).inject(:*)
0の場合に正解を示し、nil
負のパラメーターを返します。
回答:
標準ライブラリには階乗関数はありません。
Math.gamma
メソッドがあります。例:stackoverflow.com/a/37352690/407213
標準ライブラリにはありませんが、Integerクラスを拡張できます。
class Integer
def factorial_recursive
self <= 1 ? 1 : self * (self - 1).factorial
end
def factorial_iterative
f = 1; for i in 1..self; f *= i; end; f
end
alias :factorial :factorial_iterative
end
注意パフォーマンス上の理由から、反復階乗の方が適しています。
http://rosettacode.org/wiki/Factorial#Rubyから恥知らずにクリブされました。私の個人的なお気に入りは
class Integer
def fact
(1..self).reduce(:*) || 1
end
end
>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
この実装は、RosettaCodeにリストされているバリアントの中で最速です。
|| 1
ゼロの場合を処理するために追加されました。
Mark Thomasに感謝と感謝を込めて、もう少し効率的でエレガントでわかりにくいバージョンを次に示します。
class Integer
def fact
(2..self).reduce(1,:*)
end
end
reduce
:で初期値を指定することにより、ゼロの場合を処理することもできます(1..self).reduce(1,:*)
。
(2..self).reduce(1,:*)
ミクロ効率があなたのものであるならば、実際にあなたは使うことができます:)
数学でfactorial of n
は、はただgamma function of n+1
(http://en.wikipedia.org/wiki/Gamma_functionを参照)です。
Rubyは、必要に応じてMath.gamma()
それを使用Math.gamma(n+1)
して整数にキャストバックするだけです。
Math.gamma
整数パラメーターの階乗に要約される関数を使用することもできます。
class Integer
def !
(1..self).inject(:*)
end
end
!3 # => 6
!4 # => 24
class Integer ; def ! ; (1..self).inject(:*) ; end ; end
ますか?
a
たまたま...Integer
の場合、否定演算子を別のものにするのは本当に危険かもしれません!a
。そうすると、バグが存在する可能性があり、それを知るのは非常に困難です。そのa
ような大きな数である場合357264543
、プロセッサは大きなループに入り、人々はなぜプログラムが突然遅くなるのか疑問に思うかもしれません
def factorial(n=0)
(1..n).inject(:*)
end
factorial(3)
factorial(11)
を使用Math.gamma.floor
すると、近似値を生成し、それを正しい整数の結果に切り捨てる簡単な方法です。すべての整数で機能するはずです。必要に応じて入力チェックを含めてください。
n = 22
正確な答えを出すのをやめ、近似値を生成した後。
参加し、私たちを助けるために時間を費やしたすべての人に敬意を表して、ここにリストされているソリューションのベンチマークを共有したいと思います。パラメータ:
反復= 1000
n = 6
user system total real
Math.gamma(n+1) 0.000383 0.000106 0.000489 ( 0.000487)
(1..n).inject(:*) || 1 0.003986 0.000000 0.003986 ( 0.003987)
(1..n).reduce(1, :*) 0.003926 0.000000 0.003926 ( 0.004023)
1.upto(n) {|x| factorial *= x } 0.003748 0.011734 0.015482 ( 0.022795)
n = 10の場合
user system total real
0.000378 0.000102 0.000480 ( 0.000477)
0.004469 0.000007 0.004476 ( 0.004491)
0.004532 0.000024 0.004556 ( 0.005119)
0.027720 0.011211 0.038931 ( 0.058309)
Math.gamma(n+1)
もn> 22の場合にのみ概算であるため、すべてのユースケースに適しているとは限らないことに注意してください。
6.downto(1).inject(:*)