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?
6.downto(1).inject(:*)
(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 renvoienil
les paramètres négatifs.Réponses:
Il n'y a pas de fonction factorielle dans la bibliothèque standard.
la source
Math.gamma
méthode, par exemple stackoverflow.com/a/37352690/407213Comme ça c'est mieux
(1..n).inject(:*) || 1
la source
(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.
la source
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.
mise à jour n ° 1
Ajouté
|| 1
pour gérer le cas zéro.mise à jour # 2
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
la source
reduce
:(1..self).reduce(1,:*)
.(2..self).reduce(1,:*)
, si la micro-efficacité est votre truc :)En maths,
factorial of n
c'est juste legamma 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.la source
Vous pouvez également utiliser une
Math.gamma
fonction qui se résume à factorielle pour les paramètres entiers.la source
0..22
: MRI Ruby effectue en fait une recherche pour ces valeurs (voirstatic 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
exemples
!3 # => 6 !4 # => 24
la source
class Integer ; def ! ; (1..self).inject(:*) ; end ; end
?a
qu'il se trouveInteger
dans le cas de!a
... cela peut provoquer un bogue qui est très difficile à dire. S'ila
se trouve qu'il s'agit d'un grand nombre comme celui-ci,357264543
le processeur entre dans une grande boucle et les gens peuvent se demander pourquoi le programme devient soudainement lentje ferais
(1..n).inject(1, :*)
la source
Je viens d'écrire le mien:
def fact(n) if n<= 1 1 else n * fact( n - 1 ) end end
En outre, vous pouvez définir une factorielle décroissante:
def fall_fact(n,k) if k <= 0 1 else n*fall_fact(n - 1, k - 1) end end
la source
Appelez simplement cette fonction
def factorial(n=0) (1..n).inject(:*) end
exemples
factorial(3) factorial(11)
la source
L'utilisation
Math.gamma.floor
est 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.la source
n = 22
qu'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)
la source
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
la source
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.
la source
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
la source
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
la source
Et encore une autre façon (=
def factorial(number) number = number.to_i number_range = (number).downto(1).to_a factorial = number_range.inject(:*) puts "The factorial of #{number} is #{factorial}" end factorial(#number)
la source
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
la source
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
la source