Domanda

'Semplice' domanda, qual è il modo più veloce per calcolare il coefficiente binomiale? -? Alcuni filettato algoritmo

Sto cercando i suggerimenti :) - non implementazioni:)

È stato utile?

Soluzione

Secondo l'equazione di seguito (da wikipedia ) il modo più veloce sarebbe quella di dividere la variare i = 1, k per il numero di fili, invia ogni filo un segmento gamma, e ogni filo aggiorna il risultato finale di una serratura. "Modo accademico" sarebbe quello di dividere il campo in attività, ogni compito è quello di calcolare (n - k + i) / i, e quindi non importa quante discussioni che hai, tutti corrono in un ciclo chiedendo prossimo compito. In primo luogo è più veloce, il secondo è ... accademica.

alt text

EDIT: ulteriori spiegazioni - in entrambi i modi abbiamo qualche numero arbitrario di thread. Di solito il numero di fili è uguale al numero di core, perché non v'è alcun vantaggio in aggiunta più thread. La differenza tra i due modi è quello che questi fili stanno facendo.

In primo modo ogni filo è dato N, K, I1 e I2, dove I1 e I2 sono il segmento nell'intervallo 1..K. Ogni filo ha quindi tutti i dati che NEADS, quindi calcola parte del risultato sua, e sulla finitura aggiorna il risultato finale.

In secondo modo ogni filo è dato N, K, e l'accesso ad alcune contatore sincronizzato che conta da 1 a K. Ciascun thread quindi acquisisce un valore di questo contatore condivisa, calcola una frazione del risultato, aggiorna il risultato finale, e loop su questo, fino contatore informa il filo che non ci sono più elementi. Se accade che alcuni processor core sono più veloci che altri allora questo secondo modo metterà tutti i core di massimo utilizzo. Inconveniente di secondo modo è troppo sincronizzazione che blocca efficacemente, diciamo, 20% di fili per tutto il tempo.

Altri suggerimenti

Bene il modo più veloce, mi sa, sarebbe quello di leggerli da una tabella di calcolo, piuttosto che loro.

I requisiti di precisione intero da utilizzando un doppio mezzo di rappresentazione che C (60,30) è tutto, ma troppo grande, essendo intorno 1e17, in modo che (supponendo che si desidera avere C (m, n) per ogni m fino a qualche limite, e ogni n <= m), la tabella avrebbe solo circa 1800 voci. Per quanto riguarda la compilazione della tabella in Credo che il triangolo di Pascal è la strada da percorrere.

Suggerimento: Si vuole fare il meno possibile di moltiplicazioni. La formula è n! / (k! * (n-k)!). Si dovrebbe fare a meno di moltiplicazioni 2m, dove m è il minimo di k e n-k. Se si vuole lavorare con (relativamente) grandi numeri, è necessario utilizzare una classe speciale per la rappresentazione numerica (Java ha BigInteger per esempio).

Ecco un modo che non è mai trabocca se il risultato finale è esprimibili in modo nativo nella macchina, non comporta moltiplicazioni / fattorizzazioni, è facilmente parallelizzata, e generalizza a BigInteger tipi:

Per prima cosa nota che i coefficienti binomiali soddisfano seguente:

binomnk.

Questo produce una ricorsione semplice per il calcolo del coefficiente: i casi di base sono  binomrr e binomr0, entrambi i quali sono 1.

I singoli risultati dei subcalls sono interi e se \ binom {n} {k} può essere rappresentato da un int, anche loro possono; così, troppo pieno non è un problema.

Ingenuamente attuazione, i conduttori ricorsione per subcalls utilizzate e runtime esponenziali.

Questo può essere risolto memorizzando risultati intermedi. Ci sono n ^ 2 sottoproblemi, che possono essere combinati in O (1) tempo, ottenendo un O (n ^ 2) complessità legati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top