Je deviens fou: où est la fonction Ruby pour factorielle? Non, je n'ai pas besoin d'implémentations de tutoriel, je veux juste la fonction de la bibliothèque. Ce n'est pas en maths!
Je commence à douter, est-ce une fonction de bibliothèque standard?
Je deviens fou: où est la fonction Ruby pour factorielle? Non, je n'ai pas besoin d'implémentations de tutoriel, je veux juste la fonction de la bibliothèque. Ce n'est pas en maths!
Je commence à douter, est-ce une fonction de bibliothèque standard?
(1..6).inject(:*)qui est un peu plus succinct.
(1..num).inject(:*)échoue pour le cas où num == 0. (1..(num.zero? ? 1 : num)).inject(:*)donne la bonne réponse pour le cas 0 et renvoie nilles paramètres négatifs.
Réponses:
Il n'y a pas de fonction factorielle dans la bibliothèque standard.
Math.gammaméthode, par exemple stackoverflow.com/a/37352690/407213
Comme ça c'est mieux
(1..n).inject(:*) || 1
(1..n).reduce(1, :*).
Ce n'est pas dans la bibliothèque standard mais vous pouvez étendre la classe 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
NB La factorielle itérative est un meilleur choix pour des raisons évidentes de performances.
Honteusement cribbed de http://rosettacode.org/wiki/Factorial#Ruby , mon préféré est
class Integer
def fact
(1..self).reduce(:*) || 1
end
end
>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Cette implémentation est également la plus rapide parmi les variantes répertoriées dans Rosetta Code.
Ajouté || 1pour gérer le cas zéro.
Avec nos remerciements et nos remerciements à Mark Thomas , voici une version un peu plus efficace, élégante et obscure:
class Integer
def fact
(2..self).reduce(1,:*)
end
end
reduce: (1..self).reduce(1,:*).
(2..self).reduce(1,:*), si la micro-efficacité est votre truc :)
En maths, factorial of nc'est juste le gamma function of n+1
(voir: http://en.wikipedia.org/wiki/Gamma_function )
Ruby a Math.gamma()donc juste utilisé Math.gamma(n+1)et converti en un entier si vous le souhaitez.
Vous pouvez également utiliser une Math.gammafonction qui se résume à factorielle pour les paramètres entiers.
0..22: MRI Ruby effectue en fait une recherche pour ces valeurs (voir static const double fact_table[]dans la source ). Au-delà de cela, c'est une approximation. 23 !, par exemple, nécessite une mantisse de 56 bits qu'il est impossible de représenter avec précision en utilisant le double IEEE 754 qui a une mantisse de 53 bits.
class Integer
def !
(1..self).inject(:*)
end
end
!3 # => 6
!4 # => 24
class Integer ; def ! ; (1..self).inject(:*) ; end ; end?
aqu'il se trouve Integerdans le cas de !a... cela peut provoquer un bogue qui est très difficile à dire. S'il ase trouve qu'il s'agit d'un grand nombre comme celui-ci, 357264543le processeur entre dans une grande boucle et les gens peuvent se demander pourquoi le programme devient soudainement lent
def factorial(n=0)
(1..n).inject(:*)
end
factorial(3)
factorial(11)
L'utilisation Math.gamma.floorest un moyen simple de produire une approximation, puis de l'arrondir au résultat entier correct. Devrait fonctionner pour tous les nombres entiers, incluez une vérification d'entrée si nécessaire.
n = 22qu'il cesse de donner une réponse exacte et produit des approximations.
Avec le plus grand respect pour tous ceux qui ont participé et passé leur temps à nous aider, je voudrais partager mes points de repère des solutions énumérées ici. Paramètres:
itérations = 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)
Pour 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'est également approximatif que pour n> 22, il peut donc ne pas convenir à tous les cas d'utilisation.
Juste une autre façon de le faire, même si ce n'est vraiment pas nécessaire.
class Factorial
attr_reader :num
def initialize(num)
@num = num
end
def find_factorial
(1..num).inject(:*) || 1
end
end
number = Factorial.new(8).find_factorial
puts number
Vous trouverez probablement une demande de fonctionnalité Ruby utile. Il contient un correctif non trivial qui inclut un script de démonstration Bash . La différence de vitesse entre une boucle naïve et la solution présentée dans le lot peut être littéralement 100x (cent fois). Tout écrit en rubis pur.
Voici ma version qui me semble claire même si elle n'est pas aussi propre.
def factorial(num)
step = 0
(num - 1).times do (step += 1 ;num *= step) end
return num
end
C'était ma ligne de test irb qui montrait chaque étape.
num = 8;step = 0;(num - 1).times do (step += 1 ;num *= step; puts num) end;num
class Integer
def factorial
return self < 0 ? false : self==0 ? 1 : self.downto(1).inject(:*)
#Not sure what other libraries say, but my understanding is that factorial of
#anything less than 0 does not exist.
end
end
Encore une façon de le faire:
# fact(n) => Computes the Factorial of "n" = n!
def fact(n) (1..n).inject(1) {|r,i| r*i }end
fact(6) => 720
Pourquoi la bibliothèque standard nécessiterait-elle une méthode factorielle, alors qu'il existe un itérateur intégré à cet effet précis? Cela s'appelle upto.
Non, vous n'avez pas besoin d'utiliser la récursivité, comme le montrent toutes ces autres réponses.
def fact(n)
n == 0 ? 1 : n * fact(n - 1)
end
Au contraire, l'itérateur intégré jusqu'à peut être utilisé pour calculer les factorielles:
factorial = 1
1.upto(10) {|x| factorial *= x }
factorial
=> 3628800
6.downto(1).inject(:*)