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?
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?
(1..6).inject(:*)
yang lebih ringkas.
(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 nil
untuk parameter negatif.
Jawaban:
Tidak ada fungsi faktorial di perpustakaan standar.
Math.gamma
metode, misalnya stackoverflow.com/a/37352690/407213
Seperti ini lebih baik
(1..n).inject(:*) || 1
(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.
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.
Ditambahkan || 1
untuk menangani kasus nol.
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
reduce
: (1..self).reduce(1,:*)
.
(2..self).reduce(1,:*)
, jika efisiensi mikro adalah hal Anda :)
Dalam matematika, factorial of n
hanya gamma function of n+1
(lihat: http://en.wikipedia.org/wiki/Gamma_function )
Ruby Math.gamma()
hanya menggunakan Math.gamma(n+1)
dan melemparkannya kembali ke integer jika diinginkan.
Anda juga bisa menggunakan Math.gamma
fungsi yang bermuara pada faktorial untuk parameter integer.
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.
class Integer
def !
(1..self).inject(:*)
end
end
!3 # => 6
!4 # => 24
class Integer ; def ! ; (1..self).inject(:*) ; end ; end
?
a
kebetulan terjadi Integer
dalam kasus !a
... melakukan hal itu dapat menyebabkan ada bug yang sangat sulit untuk diceritakan. Jika a
kebetulan jumlahnya besar seperti 357264543
maka prosesor akan berputar besar dan orang mungkin bertanya-tanya mengapa program tiba-tiba menjadi lambat
def factorial(n=0)
(1..n).inject(:*)
end
factorial(3)
factorial(11)
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.
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)
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
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.
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
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
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
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
6.downto(1).inject(:*)