Calcul numérique = calcul en utilisant des nombres, en général en virgule flottante.
Calcul numérique $\neq$ calcul symbolique.
Nombre flottant : signe + mantisse (« chiffres significatifs ») + exposant.
Valeur d'un flottant = $(-1)^\mbox{signe} + 1.\mbox{mantisse} * 2^\mbox{exposant}$
Précision avec les flottants Python (double précision = 64 bits) :
1 bit de signe
52 bits de mantisse ($\Rightarrow$ environ 15 à 16 décimales significatives)
11 bits d'exposant ($\Rightarrow$ représentation des nombres de $10^{-308}$ à $10^{308}$)
On admet que (Grégory-Leibniz) :
$$\arctan(1) = \frac{\pi}{4} = \sum_{n=0}^\infty \frac{(-1)^n}{2n+1}$$Pour calculer $\pi$ avec des nombres flottants, il y a plusieurs problèmes de précision :
Le résultat attendu n'est pas un flottant représentable (il n'est même pas rationnel). Le meilleur calcul de $\pi$ possible ne pourra donner qu'un arrondi à $\approx 10^{-15}$ près.
En utilisant des nombres flottants, chaque opération (/, +, ...) peut faire une erreur d'arrondi (erreur relative de $10^{-15}$). Les erreurs peuvent se cumuler.
La formule mathématique est infinie. Le calcul informatique sera forcé de s'arrêter après un nombre fini d'itérations.
def gregory_leibniz(N):
result = 0
denom = 1
signe = 1
for k in range(N):
result = result + signe / float(denom)
# prepare iteration suivante:
denom = denom + 2
signe = -signe
return result * 4
print(gregory_leibniz(1))
print(gregory_leibniz(10))
print(gregory_leibniz(100))
print(gregory_leibniz(1000))
# Changer la précision de l'affichage (et seulement de l'affichage)
%precision 18
gregory_leibniz(10 ** 8)
import math
math.pi
# Retour à la valeur par défaut
%precision
1.0 / 3 - 1.0 / 4 - 1.0 / 12
1 + 1e-16 - 1
1 - 1 + 1e-16
1.2 - 1.0 - 0.2
1.2
n'est pas représentable en machine. L'ordinateur utilise « le flottant représentable le plus proche de 1.2 » à la place ...
On ne peut pas espérer de résultat exact
La précision du calcul dépend de beaucoup d'éléments (en particulier l'ordre d'évaluation : en général la précision est meilleure en sommant du plus petit au plus grand)
tester x == 0.0
avec un flottant est presque toujours une erreur.
Si on s'y prend bien, on perd $\approx 10^{-16}$ en précision relative à chaque calcul $\Rightarrow$ acceptable par rapport à la précision des données.
Si on s'y prend mal, le résultat peut être complètement faux !
Soit $f$ une fonction continue qui change de signe entre $a$ et $b$ avec $f(a) < 0$ et $f(b) > 0$.
def zero_dichotomie(f, a, b, epsilon):
while b - a > epsilon:
pivot = (a + b) / 2.0
value = f(pivot)
if value <= 0:
a = pivot
else:
b = pivot
return a
zero_dichotomie(lambda x : x ** 2 - 2, 0.0, 2.0, 1e-15)
math.sqrt(2)