Jika Anda masih ingin menghitung nilainya sendiri, Anda dapat menggunakan memoization :
var f = [];
functionfactorial (n) {
if (n == 0 || n == 1)
return1;
if (f[n] > 0)
return f[n];
return f[n] = factorial(n-1) * n;
}
Edit: 21.08.2014
Solusi 2
Saya pikir akan berguna untuk menambahkan contoh kerja fungsi faktorial iteratif malas yang menggunakan angka besar untuk mendapatkan hasil yang tepat dengan memoization dan cache sebagai perbandingan
var f = [new BigNumber("1"), new BigNumber("1")];
var i = 2;
functionfactorial(n)
{
if (typeof f[n] != 'undefined')
return f[n];
var result = f[i-1];
for (; i <= n; i++)
f[i] = result = result.multiply(i.toString());
return result;
}
var cache = 100;
// Due to memoization, following line will cache first 100 elements.
factorial(cache);
Saya berasumsi Anda akan menggunakan semacam closure untuk membatasi visibilitas nama variabel.
Nilai setelah 6402373705728000 akan dipotong jadi jika Anda akan menggunakan pendekatan ini, pastikan untuk mengubahnya menjadi eksponensial sebelum menggunakan tabel yang disebutkan di atas.
David Scott Kirby
1
@DavidScottKirby Javascript secara otomatis mengonversi angka-angka ini ke representasi float 64-bit terdekat. Manfaat nyata dari tidak adanya angka presisi penuh dalam kode adalah mengurangi ukuran file.
le_m
Solusi kedua Anda dapat disederhanakan menjadi function factorial (n) { for (var i = f.length; i <= n; i++) f.push(f[i - 1].multiply(i.toString())); return f[n]; }Juga lihat jawaban saya yang menggunakan bawaan yang BigIntlebih baru daripada perpustakaan pihak ketiga.
Patrick Roberts
jadi, nomor 100 memiliki panjang 158 karakter
Barbu Barbu
99
Anda harus menggunakan loop.
Berikut adalah dua versi yang diukur dengan menghitung faktorial 100 untuk 10.000 kali.
Rekursif
functionrFact(num)
{
if (num === 0)
{ return1; }
else
{ return num * rFact( num - 1 ); }
}
Iteratif
functionsFact(num)
{
var rval=1;
for (var i = 2; i <= num; i++)
rval = rval * i;
return rval;
}
+1 Jawaban bagus! Meskipun memoisasi mungkin masuk akal ketika ada beberapa panggilan untuk menghitung faktorial untuk nomor yang lebih besar.
Tadeck
@Tadeck, terima kasih. Memang memoisasi sangat berguna dalam kasus ini dan itulah mengapa jawaban Margus dipilih sebagai yang benar :)
Gabriele Petrioli
Versi rekursif 1 baris: function factorial (num) {return (num == 1)? num: num * arguments.callee (num-1); }
jbyrd
2
@HWTech, Anda tidak pernah memanggil metode tersebut. Pengujian Anda membandingkan kecepatan dalam menentukan kedua metode .. bukan waktu yang mereka
butuhkan
4
Alih-alih rval = rval * i;Anda bisa menulisrval *= i;
Ryan
29
Saya masih berpikir jawaban Margus adalah yang terbaik. Namun jika Anda ingin menghitung faktorial angka dalam rentang 0 hingga 1 (yaitu fungsi gamma) juga, Anda tidak dapat menggunakan pendekatan itu karena tabel pemeta harus berisi nilai tak hingga.
Namun, Anda dapat memperkirakan nilai faktorial, dan ini cukup cepat, lebih cepat daripada memanggil dirinya sendiri secara rekursif atau setidaknya mengulanginya (terutama ketika nilai mulai menjadi lebih besar).
Metode perkiraan yang baik adalah metode Lanczos
Berikut adalah implementasi dalam JavaScript (porting dari kalkulator yang saya tulis bulan lalu):
functionfactorial(op) {
// Lanczos Approximation of the Gamma Function// As described in Numerical Recipes in C (2nd ed. Cambridge University Press, 1992)var z = op + 1;
var p = [1.000000000190015, 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 1.208650973866179E-3, -5.395239384953E-6];
var d1 = Math.sqrt(2 * Math.PI) / z;
var d2 = p[0];
for (var i = 1; i <= 6; ++i)
d2 += p[i] / (z + i);
var d3 = Math.pow((z + 5.5), (z + 0.5));
var d4 = Math.exp(-(z + 5.5));
d = d1 * d2 * d3 * d4;
return d;
}
Anda sekarang dapat melakukan hal-hal keren seperti factorial(0.41), dll. Namun, akurasinya mungkin sedikit salah, bagaimanapun juga, ini adalah perkiraan hasilnya.
Baru saja menghemat banyak waktu, terima kasih banyak :)
nicolaskruchten
Saya sarankan untuk mengubah bagian di bawah for-loop menjadi var d3d4 = Math.exp((z + 0.5) * Math.log(z + 5.5) - z - 5.5); return d1 * d2 * d3d4;. Ini memungkinkan Anda untuk menghitung faktorial hingga 169! bukannya saat ini hanya 140 !. Ini cukup dekat dengan faktorial terwakili maksimum yang menggunakan Numbertipe data, yaitu 170 !.
le_m
18
Tabel pemeta adalah cara yang tepat untuk digunakan, jika Anda menggunakan bilangan asli. Untuk menghitung faktorial apa pun secara real-time, Anda dapat mempercepatnya dengan cache, menyimpan angka-angka yang telah Anda hitung sebelumnya. Sesuatu seperti:
Saya telah membuat sebuah auto-memoizer untuk setiap fungsi berdasarkan jawaban ini (juga sedikit lebih cepat :)), juga termasuk batasan ukuran cache. stackoverflow.com/a/10031674/36537
Phil H
16
Inilah solusi saya:
functionfac(n){
return(n<2)?1:fac(n-1)*n;
}
Ini adalah cara paling sederhana (lebih sedikit karakter / baris) yang saya temukan, hanya fungsi dengan satu baris kode.
Sunting:
Jika Anda benar-benar ingin menyimpan beberapa karakter, Anda dapat menggunakan Fungsi Panah (21 byte) :
factorial = n => n <= 1 ? 1 : factorial(n - 1) * n
Naramsim
10
fungsi rekursif yang singkat dan mudah (Anda juga dapat melakukannya dengan loop, tetapi menurut saya itu tidak akan membuat perbedaan dalam performa):
Saya pikir solusi terbaik adalah dengan menggunakan nilai-nilai cache, sebagai Margus disebutkan dan menggunakan Stirlings pendekatan untuk nilai-nilai yang lebih besar (diasumsikan Anda harus benar-benar cepat dan tidak harus yang sebenarnya di nomor besar seperti).
Dalam bahasa tanpa pengoptimalan panggilan ekor (yaitu bahasa yang paling banyak digunakan), lebih baik menggunakan implementasi non-rekursif yang mudah dilakukan, meskipun ada beberapa cara untuk mengatasinya: paulbarry.com/articles/2009/08/30 / tail-call-optimization
Daniel Earwicker
itu memang tidak secepat itu, karena TCO bahkan tidak akan digunakan, jika diterapkan. Tapi itu sederhana dan saya tidak akan meremehkannya. Pasti ini bukan yang tercepat.
haylem
Pengoptimalan panggilan ekor bahkan tidak memungkinkan untuk fungsi ini, karena panggilan rekursif tidak dalam posisi ekor.
Fred Foo
3
@Josh, ( bukan downvoter ) tercepat adalah loop dengan selisih yang cukup ..
Gabriele Petrioli
7
Lihatlah, memoizer, yang mengambil fungsi argumen tunggal dan mem-memoasinya. Ternyata sedikit lebih cepat dari solusi @ xPheRe , termasuk batas ukuran cache dan pemeriksaan terkait, karena saya menggunakan shortcircuiting dan sebagainya.
Menurut saya, versi berbasis loop ini mungkin merupakan fungsi faktorial tercepat.
functionfactorial(n, r = 1) {
while (n > 0) r *= n--;
return r;
}
// Default parameters `r = 1`,// was introduced in ES6
Dan inilah alasan saya:
Fungsi rekursif, bahkan dengan memoization, memiliki overhead panggilan fungsi (pada dasarnya mendorong fungsi ke stack) yang kinerjanya kurang dari menggunakan loop
Sementara forloop dan whileloop memiliki kinerja yang serupa, forloop tanpa ekspresi inisialisasi dan ekspresi akhir terlihat aneh; mungkin lebih baik untuk menulis for(; n > 0;)sebagaiwhile(n > 0)
Hanya dua parameter ndan rdigunakan, jadi dalam teori lebih sedikit parameter berarti lebih sedikit waktu yang dihabiskan untuk mengalokasikan memori
Menggunakan decremented loop yang memeriksa apakah nnol - Saya pernah mendengar teori bahwa komputer lebih baik dalam memeriksa bilangan biner (0 dan 1) daripada memeriksa bilangan bulat lainnya
Saya menemukan posting ini. Terinspirasi oleh semua kontribusi di sini saya datang dengan versi saya sendiri, yang memiliki dua fitur yang belum pernah saya lihat sebelumnya: 1) Pemeriksaan untuk memastikan argumennya adalah bilangan bulat non-negatif 2) Membuat unit dari cache dan fungsi untuk membuatnya menjadi satu bit kode mandiri. Untuk bersenang-senang, saya mencoba membuatnya sekompak mungkin. Beberapa orang mungkin menganggapnya elegan, yang lain mungkin menganggapnya sangat tidak jelas. Bagaimanapun, ini dia:
var fact;
(fact = function(n){
if ((n = parseInt(n)) < 0 || isNaN(n)) throw"Must be non-negative number";
var cache = fact.cache, i = cache.length - 1;
while (i < n) cache.push(cache[i++] * i);
return cache[n];
}).cache = [1];
Anda dapat mengisi cache terlebih dahulu, atau membiarkannya diisi saat panggilan lewat. Tetapi elemen awal (untuk fakta (0) harus ada atau akan rusak.
Kode untuk menghitung faktorial tergantung pada kebutuhan Anda.
Apakah Anda khawatir tentang overflow?
Rentang masukan apa yang akan Anda miliki?
Apakah lebih penting bagi Anda untuk meminimalkan ukuran atau waktu?
Apa yang akan Anda lakukan dengan faktorial?
Mengenai poin 1 dan 4, seringkali lebih berguna memiliki fungsi untuk mengevaluasi log faktorial secara langsung daripada memiliki fungsi untuk mengevaluasi faktorial itu sendiri.
Berikut adalah entri blog yang membahas masalah ini. Berikut adalah beberapa kode C # untuk menghitung faktorial log yang akan sepele untuk port ke JavaScript. Tetapi ini mungkin bukan yang terbaik untuk kebutuhan Anda tergantung pada jawaban Anda atas pertanyaan di atas.
Saya memperbaikinya di dalam kode di atas. Terima kasih!
Sandro Rosa
3
Memanfaatkan fakta bahwa Number.MAX_VALUE < 171!, kita cukup menggunakan tabel pencarian lengkap yang hanya terdiri dari 171 elemen array ringkas yang memakan kurang dari 1,4 kilobyte memori.
Fungsi pencarian cepat dengan kompleksitas waktu proses O (1) dan overhead akses array minimal akan terlihat sebagai berikut:
Ini tepat dan secepat itu menggunakan Numbertipe data. Menghitung tabel pemeta dalam Javascript - seperti yang disarankan beberapa jawaban lain - akan mengurangi presisi saat n! > Number.MAX_SAFE_INTEGER.
Mengompresi tabel runtime melalui gzip mengurangi ukurannya pada disk dari sekitar 3,6 menjadi 1,8 kilobyte.
Solusi menggunakan BigInt, fitur ES 2018 + / 2019.
Ini adalah contoh penggunaan yang berfungsi BigInt, karena banyak jawaban di sini semuanya lepas dari batas aman Number(MDN) hampir seketika. Ini bukan yang tercepat tetapi sederhana dan dengan demikian lebih jelas untuk mengadaptasi pengoptimalan lain (seperti cache dari 100 angka pertama).
functionfactorial(nat) {
let p = BigInt(1)
let i = BigInt(nat)
while (1 < i--) p *= i
return p
}
var factorial=(n)=>Array.from(
{length: n}, (v, k) => k+1) /*Generate Array [1, 2, .., n -1, n]*/
.reduce(
(a, b) => a*b, 1/*Multiply all aarray items; one with the next*/
);
var n = prompt('Give us "n", we will calculate "n!" ?');
if (n) {
alert(`${n}! = ${factorial(n)}`)
}
Hanya untuk kelengkapan, berikut adalah versi rekursif yang akan memungkinkan pengoptimalan panggilan ekor. Saya tidak yakin apakah pengoptimalan panggilan ekor dilakukan dalam JavaScript ..
functionrFact(n, acc)
{
if (n == 0 || n == 1) return acc;
elsereturn rFact(n-1, acc*n);
}
Juga perhatikan bahwa saya menambahkan ini ke objek Matematika yang merupakan literal objek sehingga tidak ada prototipe. Alih-alih hanya mengikat ini ke fungsi secara langsung.
Ini tidak benar-benar memanfaatkan memoization untuk subproblem - misalnya, Math.factorial(100); Math.factorial(500);akan menghitung perkalian 1..100 dua kali.
Barett
2
Saya percaya berikut ini adalah bagian kode yang paling berkelanjutan dan efisien dari komentar di atas. Anda dapat menggunakan ini dalam arsitektur js aplikasi global Anda ... dan, tidak perlu khawatir tentang menulisnya di banyak ruang nama (karena ini adalah tugas yang mungkin tidak memerlukan banyak penambahan). Saya telah menyertakan 2 nama metode (berdasarkan preferensi) tetapi keduanya dapat digunakan karena mereka hanya referensi.
Math.factorial = Math.fact = function(n) {
if (isNaN(n)||n<0) returnundefined;
var f = 1; while (n > 1) {
f *= n--;
} return f;
};
Dengan memulai perkalian Anda dengan n * (n-1) * (n-2) * ... * 1alih - alih sebaliknya, Anda kehilangan hingga 4 digit dengan presisi untuk n >> 20.
le_m
2
// if you don't want to update the Math object, use `var factorial = ...`Math.factorial = (function() {
var f = function(n) {
if (n < 1) {return1;} // no real error checking, could add type-checkreturn (f[n] > 0) ? f[n] : f[n] = n * f(n -1);
}
for (i = 0; i < 101; i++) {f(i);} // precalculate some valuesreturn f;
}());
factorial(6); // 720, initially cached
factorial[6]; // 720, same thing, slightly faster access, // but fails above current cache limit of 100
factorial(100); // 9.33262154439441e+157, called, but pulled from cache
factorial(142); // 2.6953641378881614e+245, called
factorial[141]; // 1.89814375907617e+243, now cached
Ini melakukan caching dari 100 nilai pertama dengan cepat, dan tidak memasukkan variabel eksternal ke dalam ruang lingkup untuk cache, menyimpan nilai sebagai properti dari objek fungsi itu sendiri, yang berarti bahwa jika Anda tahu factorial(n)telah dihitung, Anda dapat cukup menyebutnya sebagai factorial[n], yang sedikit lebih efisien. Menjalankan 100 nilai pertama ini akan membutuhkan waktu sub-milidetik di browser modern.
Dengan memulai perkalian Anda dengan n * (n-1) * (n-2) * ... * 1 alih-alih sebaliknya, Anda kehilangan hingga 4 digit dengan presisi untuk n >> 20. Juga, membuat yang tidak diinginkan variabel global idan melakukan terlalu banyak Numberkonversi dan memberikan hasil yang salah untuk 0! (seperti yang Anda nyatakan, tapi mengapa?).
le_m
2
Ini kode saya
functionfactorial(num){
var result = num;
for(i=num;i>=2;i--){
result = result * (i-1);
}
return result;
}
Jika (n> 170) e = Tak terhingga. Dan kode Anda akan menghasilkan sejumlah besar. tidak akan ada luapan?
Perdana
Hasil salah untuk factorial(0). Juga, dengan memulai perkalian Anda dengan n * (n-1) * (n-2) * ... * 1 alih-alih sebaliknya, Anda kehilangan hingga 4 digit dengan presisi untuk n >> 20. @prime: 170! > Number.MAX_VALUEdan paling baik diwakili dengan Infinity.
le_m
2
Loop yang di-cache harus tercepat (setidaknya ketika dipanggil beberapa kali)
var factorial = (function() {
var x =[];
returnfunction (num) {
if (x[num] >0) return x[num];
var rval=1;
for (var i = 2; i <= num; i++) {
rval = rval * i;
x[i] = rval;
}
return rval;
}
})();
Sekumpulan sederhana faktorial Memo yang memerlukan kalkulasi berlebihan, dapat diproses dengan "dikalikan dengan 1", atau merupakan satu digit yang merupakan persamaan sederhana yang tidak layak diproses secara langsung.
Setelah meninjau masukan dari anggota lain (tidak termasuk saran Log, meskipun saya dapat menerapkannya nanti) saya melanjutkan dan membuat skrip yang cukup sederhana. Saya mulai dengan contoh JavaScript OOP sederhana yang tidak berpendidikan dan membuat kelas kecil untuk menangani faktorial. Saya kemudian menerapkan Memoisasi versi saya yang disarankan di atas. Saya juga menerapkan Factorialization steno namun saya membuat sedikit kesalahan penyesuaian; Saya mengubah "n <2" menjadi "n <3". "n <2" masih akan memproses n = 2 yang akan menjadi sia-sia, karena Anda akan mengulang untuk 2 * 1 = 2; ini sia-sia menurut saya. Saya mengubahnya menjadi "n <3"; karena jika n adalah 1 atau 2 itu hanya akan mengembalikan n, jika 3 atau lebih itu akan mengevaluasi secara normal. Tentu saja karena aturan berlaku, saya menempatkan fungsi saya dalam urutan menurun dari eksekusi yang diasumsikan. Saya menambahkan opsi bool (true | false) untuk memungkinkan perubahan cepat antara eksekusi memo'ed dan normal (Anda tidak pernah tahu kapan Anda ingin menukar halaman Anda tanpa perlu mengubah "gaya") Seperti yang saya katakan sebelumnya variabel faktorial memoized diatur dengan 3 posisi awal, mengambil 4 karakter, dan meminimalkan perhitungan yang sia-sia. Semua yang melewati iterasi ketiga, Anda menangani matematika dua digit plus. Saya pikir jika Anda di mana cukup ngotot tentang hal itu Anda akan menjalankan pada tabel faktorial (seperti yang diterapkan). mengambil 4 karakter, dan meminimalkan perhitungan yang boros. Semua yang melewati iterasi ketiga, Anda menangani matematika dua digit plus. Saya pikir jika Anda di mana cukup ngotot tentang hal itu Anda akan menjalankan pada tabel faktorial (seperti yang diterapkan). mengambil 4 karakter, dan meminimalkan perhitungan yang boros. Semua yang melewati iterasi ketiga, Anda menangani matematika dua digit plus. Saya pikir jika Anda di mana cukup ngotot tentang hal itu Anda akan menjalankan pada tabel faktorial (seperti yang diterapkan).
Apa yang telah saya rencanakan setelah ini? local & | session storage untuk memungkinkan cache kasus per kasus dari iterasi yang diperlukan, pada dasarnya menangani masalah "tabel" yang diucapkan di atas. Ini juga akan menghemat ruang database dan server secara besar-besaran. Namun, jika Anda menggunakan localStorage Anda pada dasarnya akan menghabiskan ruang di komputer pengguna Anda hanya untuk menyimpan daftar nomor dan membuat layar mereka TERLIHAT lebih cepat, namun dalam jangka waktu yang lama dengan kebutuhan yang sangat besar ini akan menjadi lambat. Saya berpikir sessionStorage (membersihkan setelah Tab pergi) akan menjadi rute yang jauh lebih baik. Mungkin menggabungkan ini dengan server self balancing / cache dependen lokal? Pengguna A membutuhkan pengulangan X. Pengguna B membutuhkan iterasi Y. X + Y / 2 = Jumlah yang dibutuhkan dalam cache lokal. Kemudian, cukup deteksi dan ubah dengan waktu muat dan waktu eksekusi langsung untuk setiap pengguna sampai menyesuaikan diri dengan pengoptimalan untuk situs itu sendiri. Terima kasih!
Hasil edit ini menerapkan saran Tumpukan lainnya dan memungkinkan saya memanggil fungsi sebagai faktorial (benar) (5), yang merupakan salah satu tujuan saya yang ditetapkan. : 3 Saya juga menghapus beberapa penugasan yang tidak perlu, dan menyingkat beberapa nama variabel non-publik.
Kembali undefineduntuk 0 !. ES6 memungkinkan untuk diganti isNumericdengan Number.isInteger. Garis seperti factorials[0][factorials[1]]=factorials[0][factorial_index]*(factorials[1]+1);sama sekali tidak bisa dibaca.
le_m
2
Ini adalah salah satu yang menggunakan fungsi javascript yang lebih baru mengisi , memetakan , mengurangi dan konstruktor (dan sintaks panah lemak):
Math.factorial = n => n === 0 ? 1 : Array(n).fill(null).map((e,i)=>i+1).reduce((p,c)=>p*c)
Itu adalah salah satu baris kode yang sangat jelek dan tidak terbaca.
jungledev
1
Itu ide yang bagus. Daripada menelusuri panjangnya dua kali, mengapa tidak mengonversi semua logika ke fungsi pengurangan dan menggunakan nilai awalnya untuk menangani kasus tepi n === 0? Math.factorial = n => Array.from({ length: n }).reduce((product, _, i) => product * (i + 1), 1)
Selamat datang di StackOverflow dan terima kasih atas bantuan Anda. Anda mungkin ingin membuat jawaban Anda lebih baik dengan menambahkan beberapa penjelasan.
Jawaban:
Anda dapat mencari (1 ... 100)! di Wolfram | Alpha untuk menghitung sebelumnya urutan faktorial.
100 angka pertama adalah:
1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, 51090942171709440000, 1124000727777607680000, 25852016738884976640000, 620448401733239439360000, 15511210043330985984000000, 403291461126605635584000000, 10888869450418352160768000000, 304888344611713860501504000000, 8841761993739701954543616000000, 265252859812191058636308480000000, 8222838654177922817725562880000000, 263130836933693530167218012160000000, 8683317618811886495518194401280000000, 295232799039604140847618609643520000000, 10333147966386144929666651337523200000000, 371993326789901217467999448150835200000000, 13763753091226345046315979581580902400000000, 523022617466601111760007224100074291200000000, 20397882081197443358640281739902897356800000000, 815915283247897734345611269596115894272000000000, 33452526613163807108170062053440751665152000000000, 1405006117752879898543142606244511569936384000000000, 60415263063373835637355132068513997507264512000000000, 2658271574788448768043625811014615890319638528000000000, 119622220865480194561963161495657715064383733760000000000, 5502622159812088949850305428800254892961651752960000000000, 258623241511168180642964355153611979969197632389120000000000, 12413915592536072670862289047373375038521486354677760000000000, 608281864034267560872252163321295376887552831379210240000000000, 30414093201713378043612608166064768844377641568960512000000000000, 1551118753287382280224243016469303211063259720016986112000000000000, 80658175170943878571660636856403766975289505440883277824000000000000, 4274883284060025564298013753389399649690343788366813724672000000000000, 230843697339241380472092742683027581083278564571807941132288000000000000, 12696403353658275925965100847566516959580321051449436762275840000000000000, 710998587804863451854045647463724949736497978881168458687447040000000000000, 40526919504877216755680601905432322134980384796226602145184481280000000000000, 2350561331282878571829474910515074683828862318181142924420699914240000000000000, 138683118545689835737939019720389406345902876772687432540821294940160000000000000, 8320987112741390144276341183223364380754172606361245952449277696409600000000000000, 507580213877224798800856812176625227226004528988036003099405939480985600000000000000, 31469973260387937525653122354950764088012280797258232192163168247821107200000000000000, 1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000, 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000, 8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000, 544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000, 36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000, 2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000, 171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000, 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000, 850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000, 61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000, 4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000, 330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000, 24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000, 1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000, 145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000, 11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000, 894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000, 71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000, 5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000, 475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000, 39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000, 3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000, 281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000, 24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000, 2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000, 185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000, 16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000, 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000, 135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000, 12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000, 1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000, 108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000, 10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000, 991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000, 96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000, 9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000, 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000, 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Jika Anda masih ingin menghitung nilainya sendiri, Anda dapat menggunakan memoization :
var f = []; function factorial (n) { if (n == 0 || n == 1) return 1; if (f[n] > 0) return f[n]; return f[n] = factorial(n-1) * n; }
Edit: 21.08.2014
Solusi 2
Saya pikir akan berguna untuk menambahkan contoh kerja fungsi faktorial iteratif malas yang menggunakan angka besar untuk mendapatkan hasil yang tepat dengan memoization dan cache sebagai perbandingan
var f = [new BigNumber("1"), new BigNumber("1")]; var i = 2; function factorial(n) { if (typeof f[n] != 'undefined') return f[n]; var result = f[i-1]; for (; i <= n; i++) f[i] = result = result.multiply(i.toString()); return result; } var cache = 100; // Due to memoization, following line will cache first 100 elements. factorial(cache);
Saya berasumsi Anda akan menggunakan semacam closure untuk membatasi visibilitas nama variabel.
Ref : BigNumber Sandbox : JsFiddle
sumber
function factorial (n) { for (var i = f.length; i <= n; i++) f.push(f[i - 1].multiply(i.toString())); return f[n]; }
Juga lihat jawaban saya yang menggunakan bawaan yangBigInt
lebih baru daripada perpustakaan pihak ketiga.Anda harus menggunakan loop.
Berikut adalah dua versi yang diukur dengan menghitung faktorial 100 untuk 10.000 kali.
Rekursif
function rFact(num) { if (num === 0) { return 1; } else { return num * rFact( num - 1 ); } }
Iteratif
function sFact(num) { var rval=1; for (var i = 2; i <= num; i++) rval = rval * i; return rval; }
Langsung di: http://jsfiddle.net/xMpTv/
Hasil saya menunjukkan:
- Rekursif ~ 150 milidetik
- Iteratif ~ 5 milidetik ..
sumber
rval = rval * i;
Anda bisa menulisrval *= i;
Saya masih berpikir jawaban Margus adalah yang terbaik. Namun jika Anda ingin menghitung faktorial angka dalam rentang 0 hingga 1 (yaitu fungsi gamma) juga, Anda tidak dapat menggunakan pendekatan itu karena tabel pemeta harus berisi nilai tak hingga.
Namun, Anda dapat memperkirakan nilai faktorial, dan ini cukup cepat, lebih cepat daripada memanggil dirinya sendiri secara rekursif atau setidaknya mengulanginya (terutama ketika nilai mulai menjadi lebih besar).
Metode perkiraan yang baik adalah metode Lanczos
Berikut adalah implementasi dalam JavaScript (porting dari kalkulator yang saya tulis bulan lalu):
function factorial(op) { // Lanczos Approximation of the Gamma Function // As described in Numerical Recipes in C (2nd ed. Cambridge University Press, 1992) var z = op + 1; var p = [1.000000000190015, 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 1.208650973866179E-3, -5.395239384953E-6]; var d1 = Math.sqrt(2 * Math.PI) / z; var d2 = p[0]; for (var i = 1; i <= 6; ++i) d2 += p[i] / (z + i); var d3 = Math.pow((z + 5.5), (z + 0.5)); var d4 = Math.exp(-(z + 5.5)); d = d1 * d2 * d3 * d4; return d; }
Anda sekarang dapat melakukan hal-hal keren seperti
factorial(0.41)
, dll. Namun, akurasinya mungkin sedikit salah, bagaimanapun juga, ini adalah perkiraan hasilnya.sumber
var d3d4 = Math.exp((z + 0.5) * Math.log(z + 5.5) - z - 5.5); return d1 * d2 * d3d4;
. Ini memungkinkan Anda untuk menghitung faktorial hingga 169! bukannya saat ini hanya 140 !. Ini cukup dekat dengan faktorial terwakili maksimum yang menggunakanNumber
tipe data, yaitu 170 !.Tabel pemeta adalah cara yang tepat untuk digunakan, jika Anda menggunakan bilangan asli. Untuk menghitung faktorial apa pun secara real-time, Anda dapat mempercepatnya dengan cache, menyimpan angka-angka yang telah Anda hitung sebelumnya. Sesuatu seperti:
factorial = (function() { var cache = {}, fn = function(n) { if (n === 0) { return 1; } else if (cache[n]) { return cache[n]; } return cache[n] = n * fn(n -1); }; return fn; })();
Anda dapat menghitung sebelumnya beberapa nilai untuk lebih mempercepatnya.
sumber
Inilah solusi saya:
function fac(n){ return(n<2)?1:fac(n-1)*n; }
Ini adalah cara paling sederhana (lebih sedikit karakter / baris) yang saya temukan, hanya fungsi dengan satu baris kode.
Sunting:
Jika Anda benar-benar ingin menyimpan beberapa karakter, Anda dapat menggunakan Fungsi Panah (21 byte) :
f=n=>(n<2)?1:f(n-1)*n
sumber
f=n=>n?f(n-1)*n:1
...Hanya Satu baris dengan ES6
const factorial = n => !(n > 1) ? 1 : factorial(n - 1) * n;
Tampilkan cuplikan kode
const factorial = n => !(n > 1) ? 1 : factorial(n - 1) * n; function print(value) { document.querySelector('.result').innerHTML = value; }
.result { margin-left: 10px; }
<input onkeyup="print(factorial(this.value))" type="number"/> <span class="result">......</span>
sumber
factorial = n => n <= 1 ? 1 : factorial(n - 1) * n
fungsi rekursif yang singkat dan mudah (Anda juga dapat melakukannya dengan loop, tetapi menurut saya itu tidak akan membuat perbedaan dalam performa):
function factorial (n){ if (n==0 || n==1){ return 1; } return factorial(n-1)*n; }
untuk n yang sangat besar, Anda dapat menggunakan perkiraan putaran - tetapi itu hanya akan memberi Anda nilai perkiraan.
EDIT: komentar tentang mengapa saya mendapatkan suara negatif untuk ini akan menyenangkan ...
EDIT2: ini akan menjadi solusi jiwa menggunakan loop (yang akan menjadi pilihan yang lebih baik):
function factorial (n){ j = 1; for(i=1;i<=n;i++){ j = j*i; } return j; }
Saya pikir solusi terbaik adalah dengan menggunakan nilai-nilai cache, sebagai Margus disebutkan dan menggunakan Stirlings pendekatan untuk nilai-nilai yang lebih besar (diasumsikan Anda harus benar-benar cepat dan tidak harus yang sebenarnya di nomor besar seperti).
sumber
Lihatlah, memoizer, yang mengambil fungsi argumen tunggal dan mem-memoasinya. Ternyata sedikit lebih cepat dari solusi @ xPheRe , termasuk batas ukuran cache dan pemeriksaan terkait, karena saya menggunakan shortcircuiting dan sebagainya.
function memoize(func, max) { max = max || 5000; return (function() { var cache = {}; var remaining = max; function fn(n) { return (cache[n] || (remaining-- >0 ? (cache[n]=func(n)) : func(n))); } return fn; }()); } function fact(n) { return n<2 ? 1: n*fact(n-1); } // construct memoized version var memfact = memoize(fact,170); // xPheRe's solution var factorial = (function() { var cache = {}, fn = function(n) { if (n === 0) { return 1; } else if (cache[n]) { return cache[n]; } return cache[n] = n * fn(n -1); }; return fn; }());
Kira-kira 25x lebih cepat pada mesin saya di Chrome daripada versi rekursif, dan 10% lebih cepat dari xPheRe.
sumber
Fungsi faktorial tercepat
Menurut saya, versi berbasis loop ini mungkin merupakan fungsi faktorial tercepat.
function factorial(n, r = 1) { while (n > 0) r *= n--; return r; } // Default parameters `r = 1`, // was introduced in ES6
Dan inilah alasan saya:
for
loop danwhile
loop memiliki kinerja yang serupa,for
loop tanpa ekspresi inisialisasi dan ekspresi akhir terlihat aneh; mungkin lebih baik untuk menulisfor(; n > 0;)
sebagaiwhile(n > 0)
n
danr
digunakan, jadi dalam teori lebih sedikit parameter berarti lebih sedikit waktu yang dihabiskan untuk mengalokasikan memorin
nol - Saya pernah mendengar teori bahwa komputer lebih baik dalam memeriksa bilangan biner (0 dan 1) daripada memeriksa bilangan bulat lainnyasumber
Saya menemukan posting ini. Terinspirasi oleh semua kontribusi di sini saya datang dengan versi saya sendiri, yang memiliki dua fitur yang belum pernah saya lihat sebelumnya: 1) Pemeriksaan untuk memastikan argumennya adalah bilangan bulat non-negatif 2) Membuat unit dari cache dan fungsi untuk membuatnya menjadi satu bit kode mandiri. Untuk bersenang-senang, saya mencoba membuatnya sekompak mungkin. Beberapa orang mungkin menganggapnya elegan, yang lain mungkin menganggapnya sangat tidak jelas. Bagaimanapun, ini dia:
var fact; (fact = function(n){ if ((n = parseInt(n)) < 0 || isNaN(n)) throw "Must be non-negative number"; var cache = fact.cache, i = cache.length - 1; while (i < n) cache.push(cache[i++] * i); return cache[n]; }).cache = [1];
Anda dapat mengisi cache terlebih dahulu, atau membiarkannya diisi saat panggilan lewat. Tetapi elemen awal (untuk fakta (0) harus ada atau akan rusak.
Nikmati :)
sumber
Sangat sederhana menggunakan ES6
const factorial = n => n ? (n * factorial(n-1)) : 1;
Lihat contohnya di sini
sumber
Inilah salah satu solusinya:
function factorial(number) { total = 1 while (number > 0) { total *= number number = number - 1 } return total }
sumber
Menggunakan ES6, Anda dapat mencapainya dengan cepat dan singkat:
const factorial = n => [...Array(n + 1).keys()].slice(1).reduce((acc, cur) => acc * cur, 1)
sumber
Kode untuk menghitung faktorial tergantung pada kebutuhan Anda.
Mengenai poin 1 dan 4, seringkali lebih berguna memiliki fungsi untuk mengevaluasi log faktorial secara langsung daripada memiliki fungsi untuk mengevaluasi faktorial itu sendiri.
Berikut adalah entri blog yang membahas masalah ini. Berikut adalah beberapa kode C # untuk menghitung faktorial log yang akan sepele untuk port ke JavaScript. Tetapi ini mungkin bukan yang terbaik untuk kebutuhan Anda tergantung pada jawaban Anda atas pertanyaan di atas.
sumber
Ini adalah versi berbasis loop kompak
function factorial( _n ) { var _p = 1 ; while( _n > 0 ) { _p *= _n-- ; } return _p ; }
Atau Anda mungkin menimpa objek Matematika (versi rekursif):
Math.factorial = function( _x ) { return _x <= 1 ? 1 : _x * Math.factorial( --_x ) ; }
Atau bergabunglah dengan kedua pendekatan ...
sumber
Memanfaatkan fakta bahwa
Number.MAX_VALUE < 171!
, kita cukup menggunakan tabel pencarian lengkap yang hanya terdiri dari 171 elemen array ringkas yang memakan kurang dari 1,4 kilobyte memori.Fungsi pencarian cepat dengan kompleksitas waktu proses O (1) dan overhead akses array minimal akan terlihat sebagai berikut:
// Lookup table for n! for 0 <= n <= 170: const factorials = [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368e3,20922789888e3,355687428096e3,6402373705728e3,121645100408832e3,243290200817664e4,5109094217170944e4,1.1240007277776077e21,2.585201673888498e22,6.204484017332394e23,1.5511210043330986e25,4.0329146112660565e26,1.0888869450418352e28,3.0488834461171387e29,8.841761993739702e30,2.6525285981219107e32,8.222838654177922e33,2.631308369336935e35,8.683317618811886e36,2.9523279903960416e38,1.0333147966386145e40,3.7199332678990125e41,1.3763753091226346e43,5.230226174666011e44,2.0397882081197444e46,8.159152832478977e47,3.345252661316381e49,1.40500611775288e51,6.041526306337383e52,2.658271574788449e54,1.1962222086548019e56,5.502622159812089e57,2.5862324151116818e59,1.2413915592536073e61,6.082818640342675e62,3.0414093201713376e64,1.5511187532873822e66,8.065817517094388e67,4.2748832840600255e69,2.308436973392414e71,1.2696403353658276e73,7.109985878048635e74,4.0526919504877214e76,2.3505613312828785e78,1.3868311854568984e80,8.32098711274139e81,5.075802138772248e83,3.146997326038794e85,1.98260831540444e87,1.2688693218588417e89,8.247650592082472e90,5.443449390774431e92,3.647111091818868e94,2.4800355424368305e96,1.711224524281413e98,1.1978571669969892e100,8.504785885678623e101,6.1234458376886085e103,4.4701154615126844e105,3.307885441519386e107,2.48091408113954e109,1.8854947016660504e111,1.4518309202828587e113,1.1324281178206297e115,8.946182130782976e116,7.156945704626381e118,5.797126020747368e120,4.753643337012842e122,3.945523969720659e124,3.314240134565353e126,2.81710411438055e128,2.4227095383672734e130,2.107757298379528e132,1.8548264225739844e134,1.650795516090846e136,1.4857159644817615e138,1.352001527678403e140,1.2438414054641308e142,1.1567725070816416e144,1.087366156656743e146,1.032997848823906e148,9.916779348709496e149,9.619275968248212e151,9.426890448883248e153,9.332621544394415e155,9.332621544394415e157,9.42594775983836e159,9.614466715035127e161,9.90290071648618e163,1.0299016745145628e166,1.081396758240291e168,1.1462805637347084e170,1.226520203196138e172,1.324641819451829e174,1.4438595832024937e176,1.588245541522743e178,1.7629525510902446e180,1.974506857221074e182,2.2311927486598138e184,2.5435597334721877e186,2.925093693493016e188,3.393108684451898e190,3.969937160808721e192,4.684525849754291e194,5.574585761207606e196,6.689502913449127e198,8.094298525273444e200,9.875044200833601e202,1.214630436702533e205,1.506141741511141e207,1.882677176888926e209,2.372173242880047e211,3.0126600184576594e213,3.856204823625804e215,4.974504222477287e217,6.466855489220474e219,8.47158069087882e221,1.1182486511960043e224,1.4872707060906857e226,1.9929427461615188e228,2.6904727073180504e230,3.659042881952549e232,5.012888748274992e234,6.917786472619489e236,9.615723196941089e238,1.3462012475717526e241,1.898143759076171e243,2.695364137888163e245,3.854370717180073e247,5.5502938327393044e249,8.047926057471992e251,1.1749972043909107e254,1.727245890454639e256,2.5563239178728654e258,3.80892263763057e260,5.713383956445855e262,8.62720977423324e264,1.3113358856834524e267,2.0063439050956823e269,3.0897696138473508e271,4.789142901463394e273,7.471062926282894e275,1.1729568794264145e278,1.853271869493735e280,2.9467022724950384e282,4.7147236359920616e284,7.590705053947219e286,1.2296942187394494e289,2.0044015765453026e291,3.287218585534296e293,5.423910666131589e295,9.003691705778438e297,1.503616514864999e300,2.5260757449731984e302,4.269068009004705e304,7.257415615307999e306]; // Lookup function: function factorial(n) { return factorials[n] || (n > 170 ? Infinity : NaN); } // Test cases: console.log(factorial(NaN)); // NaN console.log(factorial(-Infinity)); // NaN console.log(factorial(-1)); // NaN console.log(factorial(0)); // 1 console.log(factorial(170)); // 7.257415615307999e+306 < Number.MAX_VALUE console.log(factorial(171)); // Infinity > Number.MAX_VALUE console.log(factorial(Infinity)); // Infinity
Ini tepat dan secepat itu menggunakan
Number
tipe data. Menghitung tabel pemeta dalam Javascript - seperti yang disarankan beberapa jawaban lain - akan mengurangi presisi saatn! > Number.MAX_SAFE_INTEGER
.Mengompresi tabel runtime melalui gzip mengurangi ukurannya pada disk dari sekitar 3,6 menjadi 1,8 kilobyte.
sumber
Jawaban satu baris:
const factorial = (num, accumulator) => num <= 1 ? accumulator || 1 : factorial(--num, num * (accumulator || num + 1)); factorial(5); // 120 factorial(10); // 3628800 factorial(3); // 6 factorial(7); // 5040 // et cetera
sumber
Faktorial berulang dengan
BigInt
untuk keamananIni adalah contoh penggunaan yang berfungsi
BigInt
, karena banyak jawaban di sini semuanya lepas dari batas amanNumber
(MDN) hampir seketika. Ini bukan yang tercepat tetapi sederhana dan dengan demikian lebih jelas untuk mengadaptasi pengoptimalan lain (seperti cache dari 100 angka pertama).function factorial(nat) { let p = BigInt(1) let i = BigInt(nat) while (1 < i--) p *= i return p }
Contoh Penggunaan
// 9.332621544394415e+157 Number(factorial(100)) // "933262154439441526816992388562667004907159682643816214685929638952175999 // 932299156089414639761565182862536979208272237582511852109168640000000000 // 00000000000000" String(factorial(100)) // 9332621544394415268169923885626670049071596826438162146859296389521759999 // 3229915608941463976156518286253697920827223758251185210916864000000000000 // 000000000000n factorial(100)
n
akhir literal numerik seperti1303n
menunjukkan itu aBigInt
tipe.BigInt
denganNumber
kecuali Anda secara eksplisit memaksanya, dan hal itu dapat menyebabkan hilangnya akurasi.sumber
Menggunakan fitur ES6, dapat menulis kode pada SATU baris & tanpa rekursi :
var factorial=(n)=>Array.from({length: n},(v, k) => k+1).reduce((a, b) => a*b, 1)
Tampilkan cuplikan kode
var factorial=(n)=>Array.from( {length: n}, (v, k) => k+1) /*Generate Array [1, 2, .., n -1, n]*/ .reduce( (a, b) => a*b, 1 /*Multiply all aarray items; one with the next*/ ); var n = prompt('Give us "n", we will calculate "n!" ?'); if (n) { alert(`${n}! = ${factorial(n)}`) }
sumber
Hanya untuk kelengkapan, berikut adalah versi rekursif yang akan memungkinkan pengoptimalan panggilan ekor. Saya tidak yakin apakah pengoptimalan panggilan ekor dilakukan dalam JavaScript ..
function rFact(n, acc) { if (n == 0 || n == 1) return acc; else return rFact(n-1, acc*n); }
Untuk menyebutnya:
rFact(x, 1);
sumber
Ini adalah solusi berulang yang menggunakan lebih sedikit ruang tumpukan dan menyimpan nilai yang dihitung sebelumnya dengan cara memo sendiri:
Math.factorial = function(n){ if(this.factorials[n]){ // memoized return this.factorials[n]; } var total=1; for(var i=n; i>0; i--){ total*=i; } this.factorials[n] = total; // save return total; }; Math.factorials={}; // store
Juga perhatikan bahwa saya menambahkan ini ke objek Matematika yang merupakan literal objek sehingga tidak ada prototipe. Alih-alih hanya mengikat ini ke fungsi secara langsung.
sumber
Math.factorial(100); Math.factorial(500);
akan menghitung perkalian 1..100 dua kali.Saya percaya berikut ini adalah bagian kode yang paling berkelanjutan dan efisien dari komentar di atas. Anda dapat menggunakan ini dalam arsitektur js aplikasi global Anda ... dan, tidak perlu khawatir tentang menulisnya di banyak ruang nama (karena ini adalah tugas yang mungkin tidak memerlukan banyak penambahan). Saya telah menyertakan 2 nama metode (berdasarkan preferensi) tetapi keduanya dapat digunakan karena mereka hanya referensi.
Math.factorial = Math.fact = function(n) { if (isNaN(n)||n<0) return undefined; var f = 1; while (n > 1) { f *= n--; } return f; };
sumber
n * (n-1) * (n-2) * ... * 1
alih - alih sebaliknya, Anda kehilangan hingga 4 digit dengan presisi untuk n >> 20.// if you don't want to update the Math object, use `var factorial = ...` Math.factorial = (function() { var f = function(n) { if (n < 1) {return 1;} // no real error checking, could add type-check return (f[n] > 0) ? f[n] : f[n] = n * f(n -1); } for (i = 0; i < 101; i++) {f(i);} // precalculate some values return f; }()); factorial(6); // 720, initially cached factorial[6]; // 720, same thing, slightly faster access, // but fails above current cache limit of 100 factorial(100); // 9.33262154439441e+157, called, but pulled from cache factorial(142); // 2.6953641378881614e+245, called factorial[141]; // 1.89814375907617e+243, now cached
Ini melakukan caching dari 100 nilai pertama dengan cepat, dan tidak memasukkan variabel eksternal ke dalam ruang lingkup untuk cache, menyimpan nilai sebagai properti dari objek fungsi itu sendiri, yang berarti bahwa jika Anda tahu
factorial(n)
telah dihitung, Anda dapat cukup menyebutnya sebagaifactorial[n]
, yang sedikit lebih efisien. Menjalankan 100 nilai pertama ini akan membutuhkan waktu sub-milidetik di browser modern.sumber
21! > Number.MAX_SAFE_INTEGER
, karenanya tidak dapat dengan aman direpresentasikan sebagai float 64-bit.Berikut adalah implementasi yang menghitung faktorial positif dan negatif. Cepat dan sederhana.
var factorial = function(n) { return n > 1 ? n * factorial(n - 1) : n < 0 ? n * factorial(n + 1) : 1; }
sumber
Ini yang saya buat sendiri, jangan gunakan angka di atas 170 atau di bawah 2.
function factorial(x){ if((!(isNaN(Number(x)))) && (Number(x)<=170) && (Number(x)>=2)){ x=Number(x);for(i=x-(1);i>=1;--i){ x*=i; } }return x; }
sumber
i
dan melakukan terlalu banyakNumber
konversi dan memberikan hasil yang salah untuk 0! (seperti yang Anda nyatakan, tapi mengapa?).Ini kode saya
function factorial(num){ var result = num; for(i=num;i>=2;i--){ result = result * (i-1); } return result; }
sumber
factorial(0)
. Juga, dengan memulai perkalian Anda dengan n * (n-1) * (n-2) * ... * 1 alih-alih sebaliknya, Anda kehilangan hingga 4 digit dengan presisi untuk n >> 20. @prime:170! > Number.MAX_VALUE
dan paling baik diwakili denganInfinity
.Loop yang di-cache harus tercepat (setidaknya ketika dipanggil beberapa kali)
var factorial = (function() { var x =[]; return function (num) { if (x[num] >0) return x[num]; var rval=1; for (var i = 2; i <= num; i++) { rval = rval * i; x[i] = rval; } return rval; } })();
sumber
function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n) }
var factorials=[[1,2,6],3];
var factorial = (function(memo,n) { this.memomize = (function(n) { var ni=n-1; if(factorials[1]<n) { factorials[0][ni]=0; for(var factorial_index=factorials[1]-1;factorials[1]<n;factorial_index++) { factorials[0][factorials[1]]=factorials[0][factorial_index]*(factorials[1]+1); factorials[1]++; } } }); this.factorialize = (function(n) { return (n<3)?n:(factorialize(n-1)*n); }); if(isNumeric(n)) { if(memo===true) { this.memomize(n); return factorials[0][n-1]; } return this.factorialize(n); } return factorials; });
Setelah meninjau masukan dari anggota lain (tidak termasuk saran Log, meskipun saya dapat menerapkannya nanti) saya melanjutkan dan membuat skrip yang cukup sederhana. Saya mulai dengan contoh JavaScript OOP sederhana yang tidak berpendidikan dan membuat kelas kecil untuk menangani faktorial. Saya kemudian menerapkan Memoisasi versi saya yang disarankan di atas. Saya juga menerapkan Factorialization steno namun saya membuat sedikit kesalahan penyesuaian; Saya mengubah "n <2" menjadi "n <3". "n <2" masih akan memproses n = 2 yang akan menjadi sia-sia, karena Anda akan mengulang untuk 2 * 1 = 2; ini sia-sia menurut saya. Saya mengubahnya menjadi "n <3"; karena jika n adalah 1 atau 2 itu hanya akan mengembalikan n, jika 3 atau lebih itu akan mengevaluasi secara normal. Tentu saja karena aturan berlaku, saya menempatkan fungsi saya dalam urutan menurun dari eksekusi yang diasumsikan. Saya menambahkan opsi bool (true | false) untuk memungkinkan perubahan cepat antara eksekusi memo'ed dan normal (Anda tidak pernah tahu kapan Anda ingin menukar halaman Anda tanpa perlu mengubah "gaya") Seperti yang saya katakan sebelumnya variabel faktorial memoized diatur dengan 3 posisi awal, mengambil 4 karakter, dan meminimalkan perhitungan yang sia-sia. Semua yang melewati iterasi ketiga, Anda menangani matematika dua digit plus. Saya pikir jika Anda di mana cukup ngotot tentang hal itu Anda akan menjalankan pada tabel faktorial (seperti yang diterapkan). mengambil 4 karakter, dan meminimalkan perhitungan yang boros. Semua yang melewati iterasi ketiga, Anda menangani matematika dua digit plus. Saya pikir jika Anda di mana cukup ngotot tentang hal itu Anda akan menjalankan pada tabel faktorial (seperti yang diterapkan). mengambil 4 karakter, dan meminimalkan perhitungan yang boros. Semua yang melewati iterasi ketiga, Anda menangani matematika dua digit plus. Saya pikir jika Anda di mana cukup ngotot tentang hal itu Anda akan menjalankan pada tabel faktorial (seperti yang diterapkan).
Apa yang telah saya rencanakan setelah ini? local & | session storage untuk memungkinkan cache kasus per kasus dari iterasi yang diperlukan, pada dasarnya menangani masalah "tabel" yang diucapkan di atas. Ini juga akan menghemat ruang database dan server secara besar-besaran. Namun, jika Anda menggunakan localStorage Anda pada dasarnya akan menghabiskan ruang di komputer pengguna Anda hanya untuk menyimpan daftar nomor dan membuat layar mereka TERLIHAT lebih cepat, namun dalam jangka waktu yang lama dengan kebutuhan yang sangat besar ini akan menjadi lambat. Saya berpikir sessionStorage (membersihkan setelah Tab pergi) akan menjadi rute yang jauh lebih baik. Mungkin menggabungkan ini dengan server self balancing / cache dependen lokal? Pengguna A membutuhkan pengulangan X. Pengguna B membutuhkan iterasi Y. X + Y / 2 = Jumlah yang dibutuhkan dalam cache lokal. Kemudian, cukup deteksi dan ubah dengan waktu muat dan waktu eksekusi langsung untuk setiap pengguna sampai menyesuaikan diri dengan pengoptimalan untuk situs itu sendiri. Terima kasih!
Edit 3:
var f=[1,2,6]; var fc=3; var factorial = (function(memo) { this.memomize = (function(n) { var ni=n-1; if(fc<n) { for(var fi=fc-1;fc<n;fi++) { f[fc]=f[fi]*(fc+1); fc++; } } return f[ni]; }); this.factorialize = (function(n) { return (n<3)?n:(factorialize(n-1)*n); }); this.fractal = (function (functio) { return function(n) { if(isNumeric(n)) { return functio(n); } return NaN; } }); if(memo===true) { return this.fractal(memomize); } return this.fractal(factorialize); });
sumber
undefined
untuk 0 !. ES6 memungkinkan untuk digantiisNumeric
denganNumber.isInteger
. Garis sepertifactorials[0][factorials[1]]=factorials[0][factorial_index]*(factorials[1]+1);
sama sekali tidak bisa dibaca.Ini adalah salah satu yang menggunakan fungsi javascript yang lebih baru mengisi , memetakan , mengurangi dan konstruktor (dan sintaks panah lemak):
Math.factorial = n => n === 0 ? 1 : Array(n).fill(null).map((e,i)=>i+1).reduce((p,c)=>p*c)
Edit: diperbarui untuk menangani n === 0
sumber
n === 0
?Math.factorial = n => Array.from({ length: n }).reduce((product, _, i) => product * (i + 1), 1)
function computeFactorialOfN(n) { var output=1; for(i=1; i<=n; i++){ output*=i; } return output; } computeFactorialOfN(5);
sumber