Deliriyorum: Faktöriyel için Ruby işlevi nerede? Hayır, eğitim uygulamalarına ihtiyacım yok, sadece kütüphaneden işlevi istiyorum. Matematikte değil!
Şüphe etmeye başlıyorum, bu standart bir kütüphane işlevi mi?
Deliriyorum: Faktöriyel için Ruby işlevi nerede? Hayır, eğitim uygulamalarına ihtiyacım yok, sadece kütüphaneden işlevi istiyorum. Matematikte değil!
Şüphe etmeye başlıyorum, bu standart bir kütüphane işlevi mi?
(1..6).inject(:*)
biraz daha özlü olan.
(1..num).inject(:*)
olduğu durumda başarısız olur num == 0
. (1..(num.zero? ? 1 : num)).inject(:*)
0 durumu için doğru cevabı verir ve nil
negatif parametreler için geri döner .
Yanıtlar:
Standart kitaplıkta faktöriyel işlev yoktur.
Math.gamma
yöntem var, örneğin stackoverflow.com/a/37352690/407213
Sanki bu daha iyi
(1..n).inject(:*) || 1
(1..n).reduce(1, :*)
.
Standart kitaplıkta değil, ancak Integer sınıfını genişletebilirsiniz.
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 Yinelemeli faktöryel, bariz performans nedenleri için daha iyi bir seçimdir.
Utanmazca http://rosettacode.org/wiki/Factorial#Ruby'den alıntı yapıldı , kişisel favorim
class Integer
def fact
(1..self).reduce(:*) || 1
end
end
>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Bu uygulama aynı zamanda Rosetta Kodunda listelenen varyantlar arasında en hızlı olanıdır.
|| 1
Sıfır durumu işlemek için eklendi .
Mark Thomas'a teşekkür ve minnettarlıkla , işte biraz daha verimli, zarif ve belirsiz bir versiyon:
class Integer
def fact
(2..self).reduce(1,:*)
end
end
reduce
: (1..self).reduce(1,:*)
.
(2..self).reduce(1,:*)
mikro verimlilik sizin işiniz ise kullanabilirsiniz :)
Matematikte, factorial of n
yalnızca gamma function of n+1
(bkz: http://en.wikipedia.org/wiki/Gamma_function )
Ruby bu Math.gamma()
yüzden sadece kullanır Math.gamma(n+1)
ve istenirse onu bir tam sayıya geri çevirir.
Math.gamma
Tamsayı parametreleri için faktöriyel hale gelen işlevi de kullanabilirsiniz .
0..22
: MRG Ruby aslında bu değerler için bir arama (bkz gerçekleştirir static const double fact_table[]
içinde kaynağın ). Bunun ötesinde, bu bir yaklaşım. 23!, Örneğin, 53 bitlik mantislere sahip IEEE 754 double kullanılarak tam olarak temsil edilmesi imkansız olan 56 bitlik bir mantis gerektirir.
class Integer
def !
(1..self).inject(:*)
end
end
!3 # => 6
!4 # => 24
class Integer ; def ! ; (1..self).inject(:*) ; end ; end
?
a
olur Integer
durumunda !a
... anlatmak çok zor varoldukları için bir hata neden olabilir Bunu yaparken. Böyle a
büyük bir sayı olursa 357264543
, işlemci büyük bir döngüye giriyor ve insanlar programın neden birdenbire yavaşladığını merak edebilir
def factorial(n=0)
(1..n).inject(:*)
end
factorial(3)
factorial(11)
Kullanmak Math.gamma.floor
, bir yaklaşım oluşturmanın ve ardından onu doğru tam sayı sonucuna geri yuvarlamanın kolay bir yoludur. Tüm Tamsayılar için çalışmalıdır, gerekirse bir giriş kontrolü ekleyin.
n = 22
Kesin bir cevap vermeyi bıraktıktan ve tahminler ürettikten sonra .
Katılan ve bize yardım etmek için zaman ayıran herkese büyük bir saygı ile, burada listelenen çözümlerle ilgili kıyaslamalarımı paylaşmak istiyorum. Parametreler:
yinelemeler = 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 için
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)
da yalnızca n> 22 için yaklaşık değer olduğuna dikkat etmek gerekir , bu nedenle tüm kullanım durumları için uygun olmayabilir.
Gerçekten gerekli olmasa da, bunu yapmanın başka bir yolu.
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
Muhtemelen bir Ruby özelliği isteğini faydalı bulacaksınız . Bir demo Bash betiği içeren önemsiz bir yama içerir . Saf bir döngü ile partide sunulan çözüm arasındaki hız farkı tam anlamıyla 100x (yüz kat) olabilir. Hepsi saf Ruby ile yazılmış.
İşte benim versiyonum o kadar temiz olmasa da bana net görünüyor.
def factorial(num)
step = 0
(num - 1).times do (step += 1 ;num *= step) end
return num
end
Bu, her adımı gösteren irb test hattımdı.
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
Bunu yapmanın bir yolu daha:
# fact(n) => Computes the Factorial of "n" = n!
def fact(n) (1..n).inject(1) {|r,i| r*i }end
fact(6) => 720
Tam olarak bu amaç için yerleşik bir yineleyici varken, standart kitaplık neden bir faktöryel yöntem gerektirsin? Denir upto
.
Hayır, diğer tüm cevapların gösterdiği gibi özyineleme kullanmanıza gerek yoktur.
def fact(n)
n == 0 ? 1 : n * fact(n - 1)
end
Bunun yerine, faktöriyelleri hesaplamak için yerleşik yineleyici kullanılabilir:
factorial = 1
1.upto(10) {|x| factorial *= x }
factorial
=> 3628800
6.downto(1).inject(:*)