我快疯了:阶乘的Ruby函数在哪里?不,我不需要教程实现,我只需要库中的函数。这不是数学!
我开始怀疑,这是标准库函数吗?
我快疯了:阶乘的Ruby函数在哪里?不,我不需要教程实现,我只需要库中的函数。这不是数学!
我开始怀疑,这是标准库函数吗?
(1..6).inject(:*)
更简洁。
(1..num).inject(:*)
对于的情况失败num == 0
。(1..(num.zero? ? 1 : num)).inject(:*)
给出0情况的正确答案,并返回nil
否定参数。
Answers:
标准库中没有阶乘函数。
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
在Rosetta Code中列出的变体中,这种实现也是最快的。
添加 || 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)
RubyMath.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
那么处理器将陷入一个大循环,人们可能会想知道为什么程序突然变慢了
使用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也仅近似于n> 22,因此可能并不适合所有用例。
6.downto(1).inject(:*)