#include <math.h> double exponentielle1 (double x, double epsilon) { int n; double s = 1, u = 1; for (n = 1; fabs (u) > epsilon; n++) { u = u * x / n; s = s + u; } return s; } double exponentielle (double x, double epsilon) { int n; double s = 1, u = 1; if (x < 0) return 1 / exponentielle (-x, epsilon); for (n = 1; fabs (u) > epsilon; n++) { u = u * x / n; s = s + u; } return s; } void main (void) { double x; while (1) { printf ("Entrer un réel : "); scanf ("%lf", &x); if (x < 0) printf ("%g %g %g\n", exponentielle1 (x, 1e-15), exponentielle (x, 1e-15), exp (x) ); else break; } }
Entrer un réel : -10 4.53999e-05 4.53999e-05 4.53999e-05 Entrer un réel : -20 5.62188e-09 2.06115e-09 2.06115e-09 Entrer un réel : -30 -3.06681e-05 9.35762e-14 9.35762e-14 Entrer un réel : -50 11072.9 1.92875e-22 1.92875e-22 Entrer un réel : -100 -2.91376e+25 3.72008e-44 3.72008e-44 Entrer un réel : 0
Les premiers termes de la série sont grands en valeur absolue, alors que le résultat est très petit en valeur absolue. La précision relative est fixe, de l'ordre de 10-15, donc si les sommes partielles intermédiaires atteignent 10n, le résultat n'est exact qu'à 10n-15 près.On peut faire calculer la valeur maximale de |s| ; on trouve :
x -20 -30 -40 -50 -100 Max (|s|) 2.2e+07 3.9e+11 7.4e+15 1.4e+20 5.4e+41 Erreur finale 3.6e-09 3.1e-05 3.2 11073 2.9e+25 ce qui confirme l'analyse ci-dessus.
void main (void) { double q, e; for (e = 1e-10 ; e > 1e-18 ; e = e /10 ) { q = 1 + e; q = q - 1; q = q / e; printf("%g %g\n", e, q); } }
1e-10 1 1e-11 1 1e-12 1.00009 1e-13 0.999201 1e-14 0.999201 1e-15 1.11022 1e-16 0 1e-17 0
Dès que epsilon est inférieur à 10-15, 1 + epsilon = 1.Remarque : on a décomposé les calculs: q=1+e; q=q-1; q=q/e au lieu d'écrire simplement : q=((1+e)-1)/e pour éviter qu'un bon compilateur ne simplifie le numérateur.
void main (void) { int i; double x = 1; for (i = 1 ; i < 20 ; i++ ) { x = 5 * ( 4 * (x - 1 / 5.0) - 3); printf("%g\n", x); } }
1 1 1 1 1 1 1 1 1.00002 1.00048 1.00957 1.19147 4.82945 77.589 1532.78 30636.6 612713 1.22542e+07 2.45085e+08
On calcule en fait la suite récurrente définie par :autrement dit : xn+1 - 1 = 20 (xn - 1). Cette suite est fortement instable, et 1/5 ne peut être représenté exactement en numération binaire ; on a donc une erreur initiale de l'ordre de 10-15, multipliée par 20 à chaque itération.
- x0 = 1
- xn+1 = 20 xn - 19
#include <math.h> long fibonacci (int n) { int i; long a = 0, b = 1, c; for (i = 1 ; i < n; i++) { c = a + b; a = b; b = c; } return b; } double u (int n) { double rac5 = sqrt (5), phi = (1 + rac5) / 2, x = 1; int k; for (k = 0; k < n; k++) x = x * phi; return x / rac5; } long arrondi (double x) { return (long) (x + 0.5); } void main (void) { double x; int n; for (n = 1; n <= 50; n++) { x = u (n); printf ("%2d : %12ld %12g %12ld %12ld\n", n, fibonacci (n), x, (long) x, arrondi (x) ); } }
1 : 1 0.723607 0 1 2 : 1 1.17082 1 1 3 : 2 1.89443 1 2 4 : 3 3.06525 3 3 5 : 5 4.95967 4 5 6 : 8 8.02492 8 8 7 : 13 12.9846 12 13 8 : 21 21.0095 21 21 9 : 34 33.9941 33 34 10 : 55 55.0036 55 55 11 : 89 88.9978 88 89 12 : 144 144.001 144 144 13 : 233 232.999 232 233 14 : 377 377.001 377 377 15 : 610 610 609 610 16 : 987 987 987 987 17 : 1597 1597 1596 1597 18 : 2584 2584 2584 2584 19 : 4181 4181 4180 4181 20 : 6765 6765 6765 6765 ... ... ... ... ... 30 : 832040 832040 832040 832040 31 : 1346269 1.34627e+06 1346268 1346269 32 : 2178309 2.17831e+06 2178309 2178309 33 : 3524578 3.52458e+06 3524577 3524578 34 : 5702887 5.70289e+06 5702887 5702887 35 : 9227465 9.22746e+06 9227464 9227465 36 : 14930352 1.49304e+07 14930352 14930352 37 : 24157817 2.41578e+07 24157817 24157817 38 : 39088169 3.90882e+07 39088169 39088169 39 : 63245986 6.3246e+07 63245986 63245986 40 : 102334155 1.02334e+08 102334155 102334155 41 : 165580141 1.6558e+08 165580141 165580141 42 : 267914296 2.67914e+08 267914296 267914296 43 : 433494437 4.33494e+08 433494437 433494437 44 : 701408733 7.01409e+08 701408733 701408733 45 : 1134903170 1.1349e+09 1134903170 1134903170 46 : 1836311903 1.83631e+09 1836311903 1836311903 47 : -1323752223 2.97122e+09 2147483647 2147483647 48 : 512559680 4.80753e+09 2147483647 2147483647 49 : -811192543 7.77874e+09 2147483647 2147483647 50 : -298632863 1.25863e+10 2147483647 2147483647
et le second terme, dont le signe alterne, tend rapidement vers zéro. A partir de n=15, le réel un est affiché comme un entier : sa partie fractionnaire est négligeable pour la précision d'affichage demandée.