Cel mai rapid factorial este saturarea stivei în limba rusă

Tipuri semnate

Cel mai rapid algoritm pentru calculul factorial al unui număr cu tipul int este folosind un tabel. Deoarece fluxul int duce la un comportament nedefinit (UB), valoarea maximă factorială este limitată la INT_MAX.







Pentru int pe 32 de biți, factorul maxim este fac (12) = 479001600. Prin urmare, cea mai rapidă funcție de calcul al factorului int32_t arată astfel:

Tipuri nesemnate

Pentru int nesemnificat, totul este mai interesant, poate depăși, dar fac (34) are un factor de 2 ^ 32:

Prin urmare, începând cu 34, toate rezultatele fac (uint32_t) vor fi zero.

Tipurile pe 64 de biți

Pentru numerele de pe 64 de biți, deversarea are loc după faza (20). zerouri începând cu fețele (66).

Astfel, folosind tabelul de factoriali de 66 elemente vor acoperi toate tipurile de până la 64 de biți:

Cred că cel mai rapid algoritm pentru calculul factorialului este determinat de structura facilităților de calcul.
De exemplu, formula Stirling admite o reprezentare a formei
n!

S (n) = a (n / e) n + 1/2. unde a = sqrt (2 * pi * e).
(n) = ((n + 1) 2) (ln n-1) + ln a) * log2 e = L (n) ].
În acest caz, notația binară a factorialului se termină în B (n) = [n / 2] + [n / 2 2] + [n / 2 3] +. zerouri (de exemplu, B (2k) = [2k / 2] + [2k / 2 2] +. + 2 + 1 = 2k -1) și, prin urmare, multiplicatorul este întreg.

Ca rezultat, obținem o formulă pentru un factor factorial rapid ca un număr întreg cu un factor de scală binar.
n! = [exp (L (n) * ln2) * 2 L (n) -B (n) +1/2]
care, dacă este corect aleasă, va fi exactă.

răspunsul este dat 2 decembrie 15 la ora 17:06

Întrebarea este rezolvată foarte repede cu ajutorul Google, răspunsul este luat de pe site-ul algolist.manual.ru:

Atrag atenția asupra faptului că în calcule, numărul lung este înmulțit secvențial cu cel obișnuit (de la tipul de date de bază, de exemplu, lungul int). Ca urmare, algoritmul de multiplicare are complexitatea O (m), m este lungimea numărului și este ușor de implementat.







Iată aproximarea logaritmului zecimal al factorului:

Întreaga parte va arăta numărul de semne ale numărului-1, iar cu mantisa este posibil să lucrați.

Puteți calcula factorial ca eln (n!), Și acest lucru va fi mai rapid decât multiplicarea directă. Dar aceasta nu va fi o valoare exactă pentru valorile mari ale n, unde există un câștig real în viteză.

Cu toate acestea, deseori (de exemplu, în calculul coeficienților binomiali) nu avem nevoie de factori în sine, ci de o anumită valoare care rezultă din divizarea factorului imens de alte numere de aceeași ordine și, ca rezultat, se obține un număr mic.

În acest caz, este logic să operați cu logaritmul factorialului, care este calculat (așa cum se vede, de exemplu, din codul sursă de mai sus) mult mai ușor și mai rapid. Împărțirea și multiplicarea vor fi înlocuite de diferența și suma logaritmilor. Dacă aveți nevoie de calcule cu adevărat eficiente, atunci o astfel de cale în controlul corectitudinii calculelor este cu siguranță preferabilă.

răspunsul dat 28 ianuarie '11 la 10:46

În primul rând, trebuie să renunțăm la recurs: nu vor exista cheltuieli generale pentru implementarea și plierea stivei.

În al doilea rând, puteți face multithreading: nucleul de scurgere, așa cum există în kernel - va ieși O (n) / număr de nuclee. De exemplu, 2 kernels și factorial 100: primul fir 1 * 2 *. * 50; al doilea flux 51 * 52 *. 100. Apoi multiplicați rezultatul. În al treilea rând, dezvoltând ideea numărul 2, puteți face o matrice statică cu factoriali deja calculați (pasul divizării și numărul de elemente afectează viteza generală în general)

Trebuie să numărăm factorialul 102, să luăm factorul deja calculat 100, să îl înmulțim cu 101 și 102 - rapid.

În general, toate cele 3 metode dintr-o dată - va fi destul de luminos.

Apropo, aveți posibilitatea să creați un matrice nu la timpul de compilare, dar când programul se execută. De exemplu, cu compilarea statică au existat 2 valori în matrice: 1! și 10! dar este necesar să numărăm 102! Numărăm și adăugăm 100 de factori la matrice! Dintr-o dată va trebui să numărăm 105!

Cred că nu s-ar fi întâmplat nimănui să recurgă recursiv. Precompunerea anumitor valori nu face nicio îmbunătățire, când se calculează un factorial. Firește, dacă trebuie să calculați mai multe factoriali succesiv, puteți salva rezultatele anterioare și acest lucru poate funcționa în cele din urmă pentru unitatea amortizată! Paralelizarea este un truc, iar întrebarea este mai degrabă algoritmică decât practică. - kirelagin Jan 28 '11 la 11:01 am

Întrebarea este algoritmică, dar este de natură aplicată. - Nicolas Chabanovsky ♦ 28 ianuarie '11 la 11:27

@ Matroskin în acest caz, a pus împreună toate optimizările propuse :). - kirelagin Jan 29 '11 la 11:30 dimineața







Articole similare

Trimiteți-le prietenilor: