Algorithmes de calcul du logarithme

Accueil » Approfondissement et Grand Oral » Algorithmes de calcul du logarithme

La fonction logarithme népérien est définie en classe de Terminale comme la fonction réciproque de la fonction exponentielle. Pour tout réel strictement positif \(a\), \(\ln(a)\) est ainsi l’unique solution de l’équation \(e^x=a\) sur \(\mathbb{R}\). Pourtant, historiquement, c’est bien le logarithme qui apparaît le premier.

C’est ainsi qu’en 1624, le mathématicien Henry Briggs publie dans ouvrage Arithmetica logarithmica une table de logarithme avec une précision de 14 décimales, et le tout sans calculatrice, bien entendu. L’algorithme utilisé par Briggs (et par Neper) n’utilise que les quatre opérations de base (addition, soustraction, multiplication et division), ainsi que l’extraction du racine carrée (qui emploi l’algorithme de Héron, un algorithme très efficace pour ce calcul).

Premier algorithme : moyennes arithmétiques et géométriques

Logarithme décimal

Pour tout réel strictement positif \(a\), nous appelerons logarithme en base 10 de \(a\) le réel noté \(log(a)\) et défini par \(log(a)=\dfrac{\ln(a)}{\ln(10)}\). Ainsi, si l’on connaît une méthode pour calculer le logarithme népérien d’un réel positif, il sera possible d’en déduire son logarithme décimal, et inversement – on aura en effet \(\ln(a)=\dfrac{\log(a)}{\log(e)}\). Le logarithme décimal possède des propriétés de calcul similaires à celles du logarithme népérien. En particulier…

Pour tous réels strictement positifs \(a\) et \(b\), pour tout entier relatif \(n\),

\(\log(ab)=\log(a)+\log(b)\) \(\log(\sqrt{a})=\dfrac{1}{2}\log(a)\) \(\log(a^n)=n\log(a)\)

On en déduit, en combinant les deux premières égalités que, pour tout réel strictement positif \(a\) et \(b\),
\[\log(\sqrt{ab})=\dfrac{1}{2}(\log(a)+\log(b))\]

La quantité \(\sqrt{ab}\) est appelée moyenne géométrique des réels \(a\) et \(b\).

Par ailleurs, pour tout entier relatif \(n\)

\[\log(10^n)=n \log(10)=n \dfrac{\ln(10)}{\ln(10)}=n\]

Premier algorithme de Briggs

L’algorithme suivant – qui porte parfois le nom de Briggs – permet de calculer le logarithme décimal de tout réel compris entre 1 et 10… Ce qui est amplement suffisant pour calculer le logarithme de n’importe quel nombre.

En effet, pour tout réel \(x\), il existe un réel \(a\) compris entre 1 et 10 et un entier relatif \(n\) tel que \(x=a \times 10^{n}\) (il s’agit de l’écriture scientifique étendue à tous les réels, et pas seulement aux nombres décimaux). Ainsi, on aura
\[\log(x) = \log(a \times 10^{n})=\log(a)+\log(10^n)=\log(a)+n\]

Le principe de cet algorithme ressemble beaucoup à celui de l’algorithme de dichotomie, utilisé pour trouver une valeur approchée d’une solution d’une équation. Prenons donc un réel \(a\) compris entre \(1\) et \(10\).

  • On calcule la moyenne géométrique de 1 et de 10 : cette moyenne vaut \(\sqrt{1 \times 10}\) soit environ \(3.162277\)
  • Son logarithme vaut quant à lui
    \[\log( \sqrt{1 \times 10}) = \dfrac{1}{2}(\log(1)+\log(10))=0,5\]
  • Ainsi, par croissance du logarithme sur \([1;10]\), si \(a\) est compris entre 1 et \(\sqrt{10}\), son logarithme sera compris entre 0 et 0,5… Si, en revanche, ce réel \(a\) se trouve entre \(\sqrt{10}\) et 10, alors son logarithme sera entre 0,5 et 1.

Par exemple, puisque \(5 \in [\sqrt{10};10]\), on sait dès à présent que le logarithme décimal de 5 est compris entre 0,5 et 1. On reprend alors le raisonnement précédent en utilisant les réels \(\sqrt{10}\) et \(10\) dans la première étape.

  • On calcule la moyenne géométrique de \(\sqrt{10}\) et de 10 : cette moyenne vaut \(\sqrt{ \sqrt{10} \times 10}\) soit environ \(5.623413\)
  • Son logarithme vaut quant à lui
    \[\log( \sqrt{\sqrt{10} \times 10}) = \dfrac{1}{2}(\log(\sqrt{10})+\log(10))=\dfrac{0.5+1}{2}=0.75\]
  • Ainsi, par croissance du logarithme sur \([1;10]\), si \(a\) est compris entre \(\sqrt{10}\) et \(\sqrt{ \sqrt{10} \times 10}\), son logarithme sera compris entre 0.5 et 0,75… Si, en revanche, ce réel \(a\) se trouve entre \(\sqrt{ \sqrt{10} \times 10}\) et 10, alors son logarithme sera entre 0,75 et 1.

L’algorithme complet est le suivant :

  • On souhaite calculer le logarithme décimal d’un réel a compris entre 1 et 10 avec une précision de \(10^{-p}\).
  • Initialisation
    • \(g\) vaut 1 (g represénte la borne gauche de l’intervalle)
    • \(d\) vaut 10 (d représente la borne droite de l’intervalle, a sera toujours dans l’intervalle [g,d])
    • log_g vaut 0
    • log_d vaut 1
  • Tant que l’écart entre log_g et log_d est supérieur à \(10^{-p}\)
    • On calcule la moyenne géométrique \(m\) de \(g\) et \(d\) : elle vaut \(\sqrt{gd}\)
    • On calcule la moyenne arithmétique log_m de log_g et log_d, qui correspond au logarithme de m
    • Si \(a\) est supérieur à \(m\), cela signifie que \(a\) est entre \(m\) et \(d\) et donc que \(\log(a)\) est entre log_m et log_d
      • on remplace donc la valeur de \(g\) par celle de \(m\)
      • on remplace la valeur de log_g par celle de log_m
    • Sinon, \(a\) est inférieur ou égal à \(m\), cela signifie que \(a\) est entre \(g\) et \(m\) et donc que \(\log(a)\) est entre log_g et log_m
      • on remplace donc la valeur de \(d\) par celle de \(m\)
      • on remplace la valeur de log_d par celle de log_m
  • Une fois la boucle terminée, on renvoie la valeur de log_g.

Cet algorithme peut être implémenté en Python de la manière suivante. L’appel briggs(5,10) permet alors de calculer le logarithme décimal de 5 à 10 décimales près.

Un exemple détaillé de fonctionnement de cet algorithme est notamment donné par Euler dans son Introduction à l’analyse infinitésimale

Un extrait de l'introduction à l'analyse infinitésimale d'Euler où celui-ci développe le calcul de la valeur approchée du logarithme décimal de 5

Deuxième algorithme : une suite convergente

Le second algorithme – qui porte parfois lui aussi le nom de Briggs – permet d’approcher le logarithme népérien d’un réel strictement positif. Toutefois, contrairement au premier algorithme, il ne permet pas de calculer plusieurs logarithmes en même temsp, de proche en proche.

Soit \(a\) un réel strictement positif. Pour approcher \(ln(a)\), on utilise la suite \((u_n)\) définie par \(u_0=a\) et, pour tout entier naturel \(n\), \(u_{n+1}=\sqrt{u_n}\). On peut alors montrer que \(\displaystyle \lim_{n \to + \infty}2^n(u_n-1)=\ln(a)\). En voici une démonstration, sous la forme d’exercice corrigé.

Soit \(a>0\). On considère la suite \((u_n)\) définie par \(u_0=a\) et, pour tout entier naturel \(n\), \(u_{n+1}=\sqrt{u_n}\).

  • Pour tout entier naturel \(n\), on pose \(w_n=\ln(u_n)\).
    • Montrer que la suite \((w_n)\) est géométrique et exprimer \(w_n\) en fonction de \(n\) pour tout entier naturel \(n\).
    • Exprimer \(u_n\) en fonction de \(n\) pour tout entier naturel \(n\)
    • En déduire \(\displaystyle\lim_{n \to + \infty}u_n\).
  • On rappelle qu’une fonction \(f\) est dérivable en \(a\) si le quotient \(\dfrac{f(x)-f(a)}{x-a}\) admet une limite finie quad \(x\) tend vers \(a\).
    • Que vaut \(ln^{\prime}(1)\) ?
    • En déduire la valeur de \(\displaystyle\lim_{x \to 1} \dfrac{\ln(x)}{x-1}\).
    • En déduire la valeur de \(\displaystyle\lim_{n \to + \infty}2^n(u_n-1)\). Indication : multiplier et diviser cette quantité par \(\ln(u_n)\).
Afficher/Masquer la solution
  • Pour tout entier naturel \(n\), on pose \(w_n=\ln(u_n)\).
    • Pour tout entier naturel \(n\),
      \[w_{n+1}=\ln(u_{n+1})=\ln(\sqrt{u_n})=\dfrac{1}{2}\ln(u_n)=\dfrac{1}{2}w_n\]
      La suite \((w_n)\) est donc géométrique de raison \(\dfrac{1}{2}\) et de premier terme \(w_0=\ln(u_0)=\ln(a)\). Ainsi, pour tout entier naturel \(n\), \(w_n)= \dfrac{\ln(a)}{2^n}\).
    • Pour tout entier naturel \(n\), \(u_n=\exp(w_n) = \exp\left(\dfrac{\ln(a)}{2^n}\right)\).
    • Puisque \(\displaystyle\lim_{n \to + \infty}2^n=+\infty\), il en vient que \(\displaystyle\lim_{n \to + \infty}\dfrac{\ln(a)}{2^n}=0\). La fonction exponentielle étant continue en 0, on a \(\displaystyle\lim_{n \to + \infty}u_n=e^0=1\).
    • On a \(ln^{\prime}(1)=\dfrac{1}{1}=1\)
    • Pour tout réel \(x\) strictement positif, \(\dfrac{\ln(x)}{x-1}=\dfrac{\ln(x)-\ln(1)}{x-1}\). Puisque \(ln\) est dérivable en 1, cette quantité tend vers \(ln^{\prime}(1)\) (c’est-à-dire 1) lorsque \(x\) tend vers 1.
    • Pour tout entier naturel \(n\),
      \[2^n(u_n-1) = 2^n \times \ln(u_n) \times \dfrac{u_n-1}{\ln(u_n)}\]
      Or, pour tout entier naturel \(n\),
      \[2^n \times \ln(u_n) = 2^n \times w_n = 2^n \times \dfrac{\ln(a)}{2^n} = \ln(a)\]
      Par ailleurs, puisque \(\displaystyle\lim_{n \to + \infty}u_n=1\), on a, par composition, \(\displaystyle\lim_{n \to + \infty}\dfrac{u_n-1}{\ln(u_n)}=1\). Ainsi, \(\displaystyle\lim_{n \to + \infty}2^n(u_n-1)=\ln(a)\)

Algorithme CORDIC

L’algorithme CORDIC (Coordinate Rotation Digital Computing) est un algorithme inventé en 1959 et utilisé dans les calculatrices. Ce même algorithme est adapté pour calculer les valeurs des fonctions trigonométriques. Pour celui-ci, certaines valeurs particulières du logarithme sont stockées dans la mémoire de la machine : il s’agit des valeurs approchés de \(\ln(10)\), \(\ln(2)\), \(\ln(1.1)\), \(\ln(1.01)\), \(\ln(1.001)\), \(\ln(1.0001)\)… Ces dernières sont toutes de la forme \(ln(1+10^{-k})\), où \(k\) est un entier naturel.

Prenons alors un réel \(x\) entre 1 et 10.

  • Puisque la suite \((2^n)\) tend vers \(+\infty\), il existe un entier \(n_0\) tel que \[x2^{n_0} \leqslant 10 \leqslant x \times 2^{n_0+1}\] Il s’avère que cet entier vaut au maximum 3, mais ce n’est pas important…
  • Puisque la suite \((1.1^n)\) tend vers \(+\infty\), il existe un entier \(n_1\) tel que \[x \times 2^{n_0} \times 1.1^{n_1} \leqslant 10 \leqslant x \times 2^{n_0+1} \times 1.1^{n_1+1}\]
  • Puisque la suite \((1.01^n)\) tend vers \(+\infty\), il existe un entier \(n_2\) tel que \[x \times 2^{n_0} \times 1.1^{n_1} \times 1.01^{n_2} \leqslant 10 \leqslant x \times 2^{n_0} \times 1.1^{n_1} \times 1.01^{n_2+1}\]

Et ainsi de suite : on établit un k-uplet d’entiers naturels \((n_0, n_1, n_2, \dots, n_k)\) et on approche \(x\) par la valeur \[x\simeq\dfrac{10}{2^{n_0} \times 1.1^{n_1} \times 1.01^{n_2} \times \dots \times (1+10^{-k})^{n_k}}\]
Il en vient que
\[\ln(x) \simeq \ln(10) – n_0 \ln(2)-n_1\ln(1.1)-n_2\ln(1.01)- \dots – n_k \ln(1+10^{-k})\]
Cet algoithme est très efficace puisque la multiplication par \(1+10^{-k}\) est rapide : il suffit de « décaler la virgule » puis de faire une addition. Cet algorithme peut alors être implémenté de la façon suivante.

Accueil » Approfondissement et Grand Oral » Algorithmes de calcul du logarithme