J'écris un modèle vérificateur qui repose sur le calcul d'un coefficient qui est utilisé intensivement par les algorithmes qui est le suivant:Comment optimiser ce calcul
[alt texte] [1]
où q
est double, t
un double aussi et k
un int. e
est synonyme de fonction exponentielle. Ce coefficient est utilisé dans les étapes où q
et t
ne changent pas pendant k
commence toujours de 0 jusqu'à ce que la somme de tous les coefficients précédents (de cette étape) atteint 1.
Ma première mise en œuvre était un littéral:
Bien sûr, cela n'a pas duré autant puisque le calcul de la factorielle entière était tout simplement irréalisable quand k
dépassait un petit seuil (15-20): évidemment, les résultats ont commencé à devenir fous. Donc, je réarrangé le tout en faisant des divisions supplémentaires:
let rec div_by_fact v d =
match d with
1. | 0. -> v
| d -> div_by_fact (v /. d) (d -. 1.)
let coeff q t k = div_by_fact (exp(-. q *. t) *. ((q *. t) ** (float k))) (float k)
Cette version fonctionne très bien quand q
et t
sont assez « normal », mais quand les choses devient étrange, par exemple q = 50.0
et t = 100.0
et je commence à calculer à partir k = 0 to 100
ce que je reçois est une série de 0 suivi de NaNs d'un certain nombre jusqu'à la fin.
Bien sûr, cela est dû à des opérations dont les nombres commencent à être trop proches de zéro ou à des problèmes similaires. Avez-vous une idée de la façon dont je peux optimiser la formule pour pouvoir donner des résultats suffisamment précis sur une large gamme d'entrées?
Tout devrait déjà être en 64 bits (puisque j'utilise OCaml qui utilise les doubles par défaut). Peut-être existe-t-il un moyen d'utiliser des 128 bits doubles, mais je ne sais pas comment. J'utilise OCaml mais vous pouvez fournir des idées dans la langue que vous voulez: C, C++, Java, etc. Je les ai toutes utilisées.
qu'en est-il de prendre 'log' + http://en.wikipedia.org/wiki/Stirling%27s_approximation – Anycorn
sum (k = 0, ...) x^k/k!== exp (x), donc on dirait presque que vous faites exp (-qt) * exp (qt) = 1. Ou est-ce que je manque quelque chose? Notez que si qt est grand, vous pouvez utiliser exp (qt) = exp (qt/2)^2, c'est-à-dire que vous pouvez diviser qt par 2 suffisamment de fois pour rendre la série courte, puis le quadriller autant de fois que nécessaire. la réponse désirée. Je ne sais pas si c'est utile pour ce que vous faites. –