En bref: comment puis-je exécuter Je calculer la somme d'une longue série de valeurs à virgule flottante dans le but de calculer l'échantillon moyenne et la variance de l'ensemble. Depuis Var (X) = E (X 2 sup>) - E (X) 2 sup> strong>, il suffit de maintenir compte courant de tous les numéros, la somme de tous les nombres à ce jour, et la somme des carrés de tous les numéros jusqu'à présent. p> jusqu'à présent, si bon. p> Cependant, il est absolument nécessaire que (X E 2 sup>)> E (X) 2 sup> strong>, qui, grâce à une précision en virgule flottante est pas toujours le cas. En pseudo-code, le problème est le suivant: p> a + b code> de telle sorte que toute perte de précision due à la troncature est loin de zéro em> plutôt que vers zéro
? le long Story h2>
sumOfSquares += sqrVal;
3 Réponses :
IEEE fournit quatre modes d'arrondi (en direction de -inf, vers + INF, vers 0, TonAreest). Vers + inf est ce que vous semblez vouloir. Il n'y a pas de contrôle standard en C90 ou C ++. C99 Ajout de l'en-tête Il est bien connu que l'algorithme que vous utilisez est numériquement instable et a un problème de précision. Il vaut mieux la précision de faire deux passes sur les données. P> p>
Utilise deux passes est vraiment malheureuse en raison de problèmes de performance (cela rend également l'API Laid). Pour autant que je puisse dire, l'algorithme doit être stable si vous venez d'arrondir - non?
Je me demande, quelque chose comme "SumofsQuares + = sqrval + SumofsQures / (1L << 52)" Soyez susceptible d'être stable?
@Amon, à propos de votre première question, je n'ai pas le temps de faire une analyse de stabilité réelle. Surtout que je ne le fais pas assez souvent suffisamment confiance en conséquence. Le code dans votre deuxième commentaire ne semble pas du tout équivalent (avez-vous l'intention de diviser SQrval à la place?, Dans ce cas, la mise à l'échelle ne change pas la stabilité ni la précision).
Non, j'ai eu l'intention de sumofsquares. Motivation: Double a 52 bits de précision, le 53ème bit est donc une source d'erreur potentielle. Pour vous assurer que l'estimation n'est jamais à haute et pas trop basse, je peux simplement ajouter le 53ème bit aussi. Vraisemblablement, SQLVAL est suffisamment petit pour inclure le bit, puis je suis sûr que toute erreur d'arrondi est en toute sécurité sous le seuil de 1/2 ^ 52.
Il y a un autre algorithme simple passe qui réarrise un peu le calcul. Dans
pseudocode: (source: http: //fr.wikipedia. org / wiki / algorithms_for_for_calculant_variarice ) p> Cela semble mieux se comporter en ce qui concerne les problèmes que vous avez signalés
avec l'algorithme habituel. p> p>
C'est-à-dire que j'aurais dû vérifier Wikipedia ;-). Merci, ça a l'air prometteur!
... et Wikipedia a même une version pondérée, ce qui est ce que je suis vraiment i> après, mais je pensais ne pas bouer inutilement les eaux inutilement.
Si vous ne vous inquiétez pas de la précision, mais à peu près une variance négative, pourquoi ne faites-vous pas simplement v (x) = max (0, e (x ^ 2) - e (x) ^ 2) code> p>
C'était ma solution de contournement initiale, mais j'espérais appuyer sur la sagesse débordante de Stackoverflow pour un meilleur. C'est une solution pragmatique - devrait probablement l'avoir mentionné ;-).
Triera l'ensemble et faire les mêmes calculs à partir de faibles valeurs et de procéder à des valeurs plus importantes change la situation?
Le tri est beaucoup plus courant O (n log (n)) le temps et o (n) stockage plutôt que le temps linéaire (et le facteur constant beaucoup plus bas) et le stockage constant pour la solution actuelle. Le jeu de données que je traite est arbitrairement important (plus mieux le mieux), c'est donc un problème.
Nul doute dans cela, mais cela aidera-t-elle en premier lieu?
Cela ne vous aidera pas car le problème peut se produire même dans des ensembles entièrement constants - tant que la somme des carrés et des sujets ont des erreurs de troncature de différence (qu'ils le feront), une série malheureuse peut entraîner une variance négative.