La précision d’une sum importante en virgule flottante

J’essaie de résumer un tableau sortingé de points flottants décroissants positifs. J’ai vu que la meilleure façon de les résumer est de commencer à additionner les nombres du plus bas au plus élevé. J’ai écrit ce code pour avoir un exemple de cela, cependant, la sum qui commence sur le plus grand nombre est plus précise. Pourquoi? (bien sûr, la sum 1 / k ^ 2 devrait être f = 1.644934066848226).

#include  #include  int main() { double sum = 0; int n; int e = 0; double r = 0; double f = 1.644934066848226; double x, y, c, b; double sum2 = 0; printf("introduce n\n"); scanf("%d", &n); double terms[n]; y = 1; while (e < n) { x = 1 / ((y) * (y)); terms[e] = x; sum = sum + x; y++; e++; } y = y - 1; e = e - 1; while (e != -1) { b = 1 / ((y) * (y)); sum2 = sum2 + b; e--; y--; } printf("sum from biggest to smallest is %.16f\n", sum); printf("and its error %.16f\n", f - sum); printf("sum from smallest to biggest is %.16f\n", sum2); printf("and its error %.16f\n", f - sum2); return 0; } 

Votre code crée un tableau double terms[n]; sur la stack, ce qui limite considérablement le nombre d’itérations pouvant être effectuées avant que votre programme ne se bloque.

Mais vous ne récupérez même rien dans ce tableau, il n’y a donc aucune raison de le faire. J’ai modifié votre code pour me débarrasser des terms[] :

 #include  int main() { double pi2over6 = 1.644934066848226; double sum = 0.0, sum2 = 0.0; double y; int i, n; printf("Enter number of iterations:\n"); scanf("%d", &n); y = 1.0; for (i = 0; i < n; i++) { sum += 1.0 / (y * y); y += 1.0; } for (i = 0; i < n; i++) { y -= 1.0; sum2 += 1.0 / (y * y); } printf("sum from biggest to smallest is %.16f\n", sum); printf("and its error %.16f\n", pi2over6 - sum); printf("sum from smallest to biggest is %.16f\n", sum2); printf("and its error %.16f\n", pi2over6 - sum2); return 0; } 

Par exemple, avec un milliard d'itérations, l'approche la plus petite en premier est beaucoup plus précise:

 Enter number of iterations: 1000000000 sum from biggest to smallest is 1.6449340578345750 and its error 0.0000000090136509 sum from smallest to biggest is 1.6449340658482263 and its error 0.0000000009999996 

Lorsque vous ajoutez deux nombres à virgule flottante avec des ordres de grandeur différents, les bits d’ordre inférieur du plus petit nombre sont perdus.

Lorsque vous faites la sum du plus petit au plus grand, les sums partielles augmentent comme Σ1/k² pour k de N à n , soit environ 1/n-1/N (en bleu), à comparer à 1/n² .

Lorsque vous faites la sum du plus grand au plus petit, les sums partielles augmentent comme Σ1/k² pour k de n à N , ce qui correspond à environ π²/6-1/n (en vert) à comparer à 1/n² .

Il est clair que le deuxième cas entraîne beaucoup plus de pertes de bits.

entrez la description de l'image ici