Aku jadi gila: Di mana fungsi Ruby untuk faktorial? Tidak, saya tidak memerlukan implementasi tutorial, saya hanya ingin fungsi dari perpustakaan. Ini bukan di Matematika!
Saya mulai ragu, apakah ini fungsi perpustakaan standar?
@mckeed: Atau (1..6).inject(:*)yang lebih ringkas.
sepp2k
8
mengapa Anda berharap ada satu?
Presiden James K. Polk
4
Saya ingin tahu apa status perpustakaan matematika dan sains untuk Ruby.
Andrew Grimm
5
Perhatikan saja contoh yang diberikan menggunakan inject. (1..num).inject(:*)gagal untuk kasus di mana num == 0. (1..(num.zero? ? 1 : num)).inject(:*)memberikan jawaban yang benar untuk kasus 0 dan mengembalikan niluntuk parameter negatif.
Yogh
Jawaban:
136
Tidak ada fungsi faktorial di perpustakaan standar.
Atau menentukan nilai awal langsung: (1..n).reduce(1, :*).
Andrew Marshall
77
Ini tidak ada di pustaka standar tetapi Anda dapat memperluas kelas Integer.
classIntegerdeffactorial_recursiveself <= 1 ? 1 : self * (self - 1).factorial
enddeffactorial_iterative
f = 1; for i in1..self; f *= i; end; f
endalias:factorial:factorial_iterativeend
Faktorial berulang NB adalah pilihan yang lebih baik untuk alasan kinerja yang jelas.
apa sih artinya itu ?! ya itu cepat tapi meskipun sangat tidak ramah pengguna
niccolo m.
3
itu juga salah untuk 0! - harus seperti ini: if self <= 1; 1; lain; (1..self) .reduce (: *); akhir
Tarmo
9
@allen - Jangan salahkan bahasanya jika Anda tidak dapat memahaminya. Ini berarti, ambil rentang 1 ke diri sendiri, lalu hapus elemen pertama (1) darinya (yaitu, itulah yang mengurangi arti dalam pemrograman fungsional). Kemudian hapus elemen pertama dari apa yang tersisa (2) dan kalikan (: *) bersama-sama. Sekarang hapus elemen pertama dari yang tersisa (3) dan kalikan dengan total yang berjalan. Teruskan sampai tidak ada yang tersisa (mis. Anda telah menangani seluruh jangkauan). Jika pengurangan gagal (karena array kosong dalam kasus 0!) Maka kembalikan 1 saja.
SDJMcHattie
Anda juga dapat menangani kasus nol dengan menentukan nilai awal di reduce: (1..self).reduce(1,:*).
Mark Thomas
3
Sebenarnya Anda dapat menggunakan (2..self).reduce(1,:*), jika efisiensi mikro adalah hal Anda :)
Dari dokumen: "Perhatikan bahwa gamma (n) sama dengan fakta (n-1) untuk integer n> 0. Namun gamma (n) mengembalikan float dan dapat menjadi perkiraan". Jika seseorang memperhitungkannya, itu berhasil, tetapi solusi pengurangan tampaknya jauh lebih mudah.
Michael Kohl
Terima kasih untuk ini! Naluri saya mengatakan untuk menggunakan perpustakaan standar melalui pengurangan yang ditulis khusus bila memungkinkan. Pembuatan profil mungkin menyarankan sebaliknya.
David J.
2
Catatan: Ini O (1) dan tepat untuk 0..22: MRI Ruby sebenarnya melakukan pencarian untuk nilai-nilai itu (lihat static const double fact_table[]di sumber ). Di luar itu, itu adalah perkiraan. 23 !, misalnya, membutuhkan mantissa 56-bit yang tidak mungkin direpresentasikan secara tepat menggunakan IEEE 754 double yang memiliki mantisa 53-bit.
Ada apa dengan class Integer ; def ! ; (1..self).inject(:*) ; end ; end?
Aleksei Matiushkin
@mudasobwa Saya suka, saya telah merefaktor untuk kesederhanaan.
jasonleonhard
4
Saya dengan hormat menyarankan bahwa menimpa metode contoh yang dimasukkan ke semua objek Ruby untuk mengembalikan nilai yang sebenarnya, daripada yang salah mungkin tidak membuat Anda banyak teman.
MatzFan
Mungkin sangat berbahaya untuk membuat operator negate menjadi sesuatu yang lain ketika akebetulan terjadi Integerdalam kasus !a... melakukan hal itu dapat menyebabkan ada bug yang sangat sulit untuk diceritakan. Jika akebetulan jumlahnya besar seperti 357264543maka prosesor akan berputar besar dan orang mungkin bertanya-tanya mengapa program tiba-tiba menjadi lambat
nonopolaritas
Jawaban ini lebih merupakan hal yang keren untuk dibagikan daripada contoh praktis untuk digunakan.
Menggunakan Math.gamma.flooradalah cara mudah untuk menghasilkan perkiraan dan kemudian membulatkannya kembali ke hasil bilangan bulat yang benar. Harus berfungsi untuk semua Integer, sertakan pemeriksaan input jika perlu.
Koreksi: Setelah n = 22berhenti memberikan jawaban yang tepat dan menghasilkan perkiraan.
Ayarch
2
Dengan rasa hormat yang tinggi kepada semua yang berpartisipasi dan menghabiskan waktu mereka untuk membantu kami, saya ingin membagikan tolok ukur saya dari solusi yang tercantum di sini. Parameter:
iterasi = 1000
n = 6
user system total real
Math.gamma(n+1) 0.0003830.0001060.000489 ( 0.000487)
(1..n).inject(:*) ||10.0039860.0000000.003986 ( 0.003987)
(1..n).reduce(1, :*) 0.0039260.0000000.003926 ( 0.004023)
1.upto(n) {|x| factorial *= x } 0.0037480.0117340.015482 ( 0.022795)
Untuk n = 10
user system total real
0.0003780.0001020.000480 ( 0.000477)
0.0044690.0000070.004476 ( 0.004491)
0.0045320.0000240.004556 ( 0.005119)
0.0277200.0112110.038931 ( 0.058309)
Perlu dicatat bahwa yang tercepat Math.gamma(n+1)juga hanya perkiraan untuk n> 22, jadi mungkin tidak cocok untuk semua kasus penggunaan.
Neil Slater
1
Hanya cara lain untuk melakukannya, meskipun sebenarnya tidak perlu.
classFactorialattr_reader:numdefinitialize(num)@num = num
enddeffind_factorial
(1..num).inject(:*) ||1endend
number = Factorial.new(8).find_factorial
puts number
Anda mungkin akan menemukan permintaan fitur Ruby berguna. Ini berisi patch nontrivial yang menyertakan skrip Bash demo . Perbedaan kecepatan antara loop naif dan solusi yang disajikan dalam batch secara harfiah bisa 100x (seratus kali lipat). Ditulis dengan Ruby murni.
classIntegerdeffactorialreturnself < 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.endend
deffactorial(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)
6.downto(1).inject(:*)
(1..6).inject(:*)
yang lebih ringkas.(1..num).inject(:*)
gagal untuk kasus di mananum == 0
.(1..(num.zero? ? 1 : num)).inject(:*)
memberikan jawaban yang benar untuk kasus 0 dan mengembalikannil
untuk parameter negatif.Jawaban:
Tidak ada fungsi faktorial di perpustakaan standar.
sumber
Math.gamma
metode, misalnya stackoverflow.com/a/37352690/407213Seperti ini lebih baik
(1..n).inject(:*) || 1
sumber
(1..n).reduce(1, :*)
.Ini tidak ada di pustaka standar tetapi Anda dapat memperluas kelas 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
Faktorial berulang NB adalah pilihan yang lebih baik untuk alasan kinerja yang jelas.
sumber
Tanpa malu-malu dikutip dari http://rosettacode.org/wiki/Factorial#Ruby , favorit pribadi saya adalah
class Integer def fact (1..self).reduce(:*) || 1 end end >> 400.fact => 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Implementasi ini juga merupakan yang tercepat di antara varian yang terdaftar di Rosetta Code.
perbarui # 1
Ditambahkan
|| 1
untuk menangani kasus nol.perbarui # 2
Dengan terima kasih dan penghargaan kepada Mark Thomas , berikut adalah versi yang sedikit lebih efisien, elegan, dan tidak jelas:
class Integer def fact (2..self).reduce(1,:*) end end
sumber
reduce
:(1..self).reduce(1,:*)
.(2..self).reduce(1,:*)
, jika efisiensi mikro adalah hal Anda :)Dalam matematika,
factorial of n
hanyagamma function of n+1
(lihat: http://en.wikipedia.org/wiki/Gamma_function )
Ruby
Math.gamma()
hanya menggunakanMath.gamma(n+1)
dan melemparkannya kembali ke integer jika diinginkan.sumber
Anda juga bisa menggunakan
Math.gamma
fungsi yang bermuara pada faktorial untuk parameter integer.sumber
0..22
: MRI Ruby sebenarnya melakukan pencarian untuk nilai-nilai itu (lihatstatic const double fact_table[]
di sumber ). Di luar itu, itu adalah perkiraan. 23 !, misalnya, membutuhkan mantissa 56-bit yang tidak mungkin direpresentasikan secara tepat menggunakan IEEE 754 double yang memiliki mantisa 53-bit.class Integer def ! (1..self).inject(:*) end end
contoh
!3 # => 6 !4 # => 24
sumber
class Integer ; def ! ; (1..self).inject(:*) ; end ; end
?a
kebetulan terjadiInteger
dalam kasus!a
... melakukan hal itu dapat menyebabkan ada bug yang sangat sulit untuk diceritakan. Jikaa
kebetulan jumlahnya besar seperti357264543
maka prosesor akan berputar besar dan orang mungkin bertanya-tanya mengapa program tiba-tiba menjadi lambatSaya akan melakukannya
(1..n).inject(1, :*)
sumber
Saya baru saja menulis sendiri:
def fact(n) if n<= 1 1 else n * fact( n - 1 ) end end
Selain itu, Anda dapat menentukan faktorial jatuh:
def fall_fact(n,k) if k <= 0 1 else n*fall_fact(n - 1, k - 1) end end
sumber
Panggil saja fungsi ini
def factorial(n=0) (1..n).inject(:*) end
contoh
factorial(3) factorial(11)
sumber
Menggunakan
Math.gamma.floor
adalah cara mudah untuk menghasilkan perkiraan dan kemudian membulatkannya kembali ke hasil bilangan bulat yang benar. Harus berfungsi untuk semua Integer, sertakan pemeriksaan input jika perlu.sumber
n = 22
berhenti memberikan jawaban yang tepat dan menghasilkan perkiraan.Dengan rasa hormat yang tinggi kepada semua yang berpartisipasi dan menghabiskan waktu mereka untuk membantu kami, saya ingin membagikan tolok ukur saya dari solusi yang tercantum di sini. Parameter:
iterasi = 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)
Untuk 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)
sumber
Math.gamma(n+1)
juga hanya perkiraan untuk n> 22, jadi mungkin tidak cocok untuk semua kasus penggunaan.Hanya cara lain untuk melakukannya, meskipun sebenarnya tidak perlu.
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
sumber
Anda mungkin akan menemukan permintaan fitur Ruby berguna. Ini berisi patch nontrivial yang menyertakan skrip Bash demo . Perbedaan kecepatan antara loop naif dan solusi yang disajikan dalam batch secara harfiah bisa 100x (seratus kali lipat). Ditulis dengan Ruby murni.
sumber
Ini adalah versi saya yang tampaknya jelas bagi saya meskipun tidak sebersih itu.
def factorial(num) step = 0 (num - 1).times do (step += 1 ;num *= step) end return num end
Ini adalah garis pengujian irb saya yang menunjukkan setiap langkah.
num = 8;step = 0;(num - 1).times do (step += 1 ;num *= step; puts num) end;num
sumber
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
sumber
Dan cara lain (=
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)
sumber
Satu cara lagi untuk melakukannya:
# fact(n) => Computes the Factorial of "n" = n! def fact(n) (1..n).inject(1) {|r,i| r*i }end fact(6) => 720
sumber
Mengapa pustaka standar memerlukan metode faktorial, bila ada iterator bawaan untuk tujuan yang tepat ini? Itu disebut
upto
.Tidak, Anda tidak perlu menggunakan rekursi, seperti yang ditunjukkan oleh semua jawaban lainnya.
def fact(n) n == 0 ? 1 : n * fact(n - 1) end
Sebaliknya, iterator bawaan upto dapat digunakan untuk menghitung faktorial:
factorial = 1 1.upto(10) {|x| factorial *= x } factorial => 3628800
sumber