Approximations de pi

Description


De nombreuses statistiques ont été effectuées pour montrer que la répartition des décimales de pi est analogue à une répartition faite au hasard. Pi est-il aléatoire ? Et bien non ! Les décimales de pi sont entièrement déterminées par les deux suites suivantes 1, 3, 5, 7, 9, ... et 1², 2², 3², 4², 5², ... qui sont parfaitement régulières. Si vous effectuez 4/(1+1²/(3+2²/(5+3²/(7+...)))) qu'est-ce que vous obtenez ? Vous obtenez le nombre pi !

En commençant à p2=4/(1+1²/(3+2²/5))=19/6 le programme piRa ci-joint effectue plusieurs approximations de pi avec de plus en plus de dénominateurs successifs. On affiche chaque approximation sous la forme d'une fraction. Tant que la référence choisie de pi le permet on l'affiche aussi sous la forme habituelle avec le nombre de chiffres exacts obtenus.

Que les décimales de pi soient déterminées, c'est évident, on le sait depuis très longtemps ! Mais qu'elles soient aussi la conséquence des deux suites 1, 3, 5, 7, ... et 1², 2², 3², 4², ... cela on n'y pense pas habituellement. Ce petit programme en fait la démonstration. La formulation utilisée est connue depuis longtemps, elle est due à Jean-Henri Lambert qui l'a publiée en 1770.

Ici, il faut pouvoir effectuer les opérations arithmétiques de base mathématiquement exactes sur des nombres rationnels représentés par des fractions ayant la taille aussi grande que nécessaire. On peut le faire assez facilement avec la variante de la bibliothèque GMP crée par Paul Herman. La programmation de ces calculs est aussi simple à développer qu'en utilisant les flottants de type float ou double qui sont natifs en C et C++ et qui sont bien sûr plus rapides. Si la quantité de calculs à effectuer est limitée on ne s'aperçoit pas de la différence de temps d'exécution, comme c'est le cas ici.

Les fractions successives qui sont obtenues sont des approximations de pi de plus en plus précises. Mais pour un écart donné avec la valeur exacte chacune de ces fractions n'est pas de taille minimale. On peut très facilement calculer une autre suite d'approximations de pi avec des fractions ayant, pour la même précision, des tailles plus petites en utilisant la fraction continue bien connue : pi = 3+(1/(7+1/(15+1/(1+1/(292+...))))) ( https://oeis.org/A001203 ).

Ce code est programmé avec Visual Studio Express 2012 pour Windows Desktop. Il affiche le résultat dans la console Windows. Si vous ne souhaitez pas refaire la compilation, le résultat est disponible dans le fichier out.txt qu'il est commode de lire avec Wordpad parce qu'il a une option d'affichage pour les lignes longues repliées ou non repliées.

Source :

#include "bigRa.hpp"
#include <sstream>
           
// Des approximations de pi utilisant la fraction continue : 
//  pi = 4 / (1 + 1² / (3 + 2² / (5 + 3² / (7 + ...))))
           
int main() {
    char numpi[] = "3141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647";
    char denpi[] = "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
    bigRa pi = bigRa(numpi,denpi);
    int nbc = sizeof(numpi) / sizeof(char);
    for(int i=2; i<190; i++) {
        // avec i dénominateurs successifs :
        int k, n = i;
        bigRa den = bigRa(2*n+1);
        while (n > 0) {
            den = bigRa(2*n-1) + bigRa(n)*bigRa(n) / den;
            n = n-1;
        }
        bigRa p = bigRa(4) / den;
        // on affiche la i-ième approximation p de pi 
        std::cout << "p" << i << " = " << p << std::endl;
        // pour afficher les chiffres décimaux de p qui sont exacts
        std::stringstream stream;
        stream << entier(p*bigRa(denpi));
        k = sizeof(stream.str().c_str());
        if(k < nbc && k < 999) {
            char suite[999];
            strcpy(suite, stream.str().c_str());
            int nbk;
            bool good=false;
            for(k=1; k<nbc; k++) 
                if(numpi[k] == suite[k]) nbk=k;
                else {good=true; break;}
            if(good) {
                std::cout << "p" << i << " = 3.";
                for(k=1; k <= nbk; k++) std::cout << suite[k];
                std::cout << "   (" << k << " chiffres exacts)";
                std::cout << std::endl;
            }
        }
        std::cout << std::endl;
    }
    getchar();
    return 0;
}
             

Conclusion

Merci pour vos remarques ou variantes éventuelles.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.