Fraction continue généralisée

Description

Ce programme effectue le calcul et l'affichage des fractions réduites obtenues avec une fraction continue généralisée définie par l'utilisateur. Le dossier joint contient le fichier projet (fraction.sln) pour compiler le code source pour Windows avec Visual Studio. Le code source utilise la bibliothèque GMP qui est jointe et n'a pas d'autre dépendance. Deux exemples d'utilisation sont disponibles dans le dossier Release avec pour chacun un fichier .bat pour l'exécution, un fichier .txt pour la fraction donnée et un fichier .vu.txt qui montre le contenu de la console Windows. Et leurs images sont dans le dossier principal.

Les fractions continues simples sont des cas particuliers de fractions continues généralisées et peuvent donc être utilisées. Internet permet d'obtenir beaucoup de fractions continues diverses. Par exemple, la formule pour le nombre pi de William Brounker 1620-1684 a une convergence très lente que l'on peut vérifier. On pourra facilement constater que les fractions réduites successives sont alternativement plus petites et plus grandes que la valeur finale de la formule examinée : c'est un avantage essentiel parce que la différence entre deux valeurs consécutives indique la précision de l'approximation obtenue.

Avec ce programme on peut aussi créer un nombre réel nouveau pouvant avoir une utilisation à préciser en essayant une formule particulière à choisir librement. Il y a encore des nombres réels intéressants et actuellement inconnus à découvrir.

Le code source comporte les commentaires essentiels. Le code exécutable n'est pas disponible. Le forum est utilisable pour avoir des échanges complémentaires. Et le dossier fournit un petit mode d'emploi. Le langage C++ est très bien adapté pour ce programme. On peut envisager soit des variantes soit un autre langage de programmation si on le souhaite.

      #include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <string>
#include "gmp.h"
#pragma comment(lib, "gmp.lib")  

int pgcd(int a, int b) {
   if(b == 0) return a;
   a %= b;
   return pgcd(b,a);
}

// Cette string est-elle valide pour un int ?
bool valide(std::string str) {
    for(unsigned int i=0; i < str.size(); i++) 
        if(str[i] < int('0') || str[i] > int('9')) return false;
    return true;
}

// Pour convertir une string en int
int str2int(std::string str) {
    int n = 0;
    for(unsigned int i=0; i < str.size(); i++) {
        n = n*10 + (int(str[i]) - int('0'));
    }
    return n;
}

// Calcul et affichage de la i-ième fraction réduite
void reduite(int i, std::vector<int> a, std::vector<int> b) {
    int maxi = b.size()-1;
    if(i < 0 || i > maxi) return;
    if(i == 0) {std::cout << b[0]  << " : " << std::setprecision(17) << double(b[0]); return;}
    if(i == 1) {
        int n = b[0]*b[1]+a[1];
        int p = pgcd(n, b[1]);
        std::cout << n/p << "/" << b[1]/p << " : " << std::setprecision(17) << double(n/p)/double(b[1]/p);
        return;
    }    
    if(i == 2) {
        int d = b[1]*b[2]+a[2];
        int n = b[0]*d+a[1]*b[2];
        int p = pgcd(n, d);
        std::cout << n/p << "/" << d/p << " : " << std::setprecision(17) << double(n/p)/double(d/p);
        return;
    }    
    mpq_t h2,h1,hn,k2,k1,kn;
    mpq_init(h2);
    mpq_init(h1);
    mpq_init(hn);
    mpq_init(k2);
    mpq_init(k1);
    mpq_init(kn);
    mpq_t t1, t2, p1, p2;
    mpq_init(t1);
    mpq_init(t2);
    mpq_init(p1);
    mpq_init(p2);
    // initialisations
    mpq_set_ui(h1, 1, 1);
    mpq_set_ui(hn, b[0], 1);
    mpq_set_ui(k1, 0, 1);
    mpq_set_ui(kn, 1, 1);
    int n = 1;
    while(n <= i) {
        // h2 = hn(n-2) et h1=hn(n-1)
        mpq_set(h2, h1);
        mpq_set(h1, hn);
        // k2 = kn(n-2) et k1=kn(n-1)
        mpq_set(k2, k1);
        mpq_set(k1, kn);
        // hn = b[n].h1+a[n].h2
        mpq_set_ui(t1, b[n], 1);
        mpq_mul(p1, t1, h1);
        mpq_set_ui(t2, a[n], 1);
        mpq_mul(p2, t2, h2);
        mpq_add(hn, p1, p2);
        // kn = b[n].k1+a[n].k2
        mpq_mul(p1, t1, k1);
        mpq_mul(p2, t2, k2);
        mpq_add(kn, p1, p2);
        n = n+1;
    }
    // La i-ème fraction réduite r = hn/kn
    // avec le dernier n utilisé = i
    mpq_t r;
    mpq_init(r);
    mpq_div(r, hn, kn);
    gmp_printf("%Qd", r);    
    std::cout << " : " << std::setprecision(17) << mpq_get_d(r);
}

// Pour lire les deux premières lignes du fichier nommé : fichier
bool lecture(std::string fichier, std::string &firstline, std::string &secndline) {
    std::string line;
    std::ifstream filein(fichier.c_str());
    if(!std::getline(filein, firstline)) return false;
    if(!std::getline(filein, secndline)) return false;
    return true;
}

// On lit dans la 1-ère ligne : a[1], a[2], a[3], ..., a[n] 
// avec tous les a[i] positifs.
// On lit dans la 2-ième ligne : b[0], b[1], b[2], b[3], ..., b[n] 
// avec : b[0] positif ou nul et pour i > 0 : b[i] positif
// On calcule les fractions réduites successives de :
//   x = b0 + a1/(b1+a2/(b2+a3/(b3+a4/(b4+...))))
int main(int argc, char** argv) {
    if(argc < 2 ) {
        std::cout << "Il faut faire : fraction fichier.txt" << std::endl;
        return 0;
    }
    std::string firstligne, secndligne;
    if(lecture(argv[1], firstligne, secndligne)) {
        /*
        std::cout << "ligne 1 : " << firstligne << std::endl;
        std::cout << "ligne 2 : " << secndligne << std::endl;
        */
        std::vector<int> a;
        a.push_back(0);  /* ce a[0] est inutilisé  */
        std::size_t found = firstligne.find(" ");
        while (found != std::string::npos) {
            if(found != 0) {
                std::string firststr = firstligne.substr(0, found);
                if(!valide(firststr)) {
                    std::cout << "ligne 1 invalide" << std::endl; 
                    return 0;
                }
                a.push_back(str2int(firststr));
            }
            firstligne = firstligne.substr(found+1);
            found = firstligne.find(" ");
        }
        if(firstligne.size() != 0) {
            if(!valide(firstligne)) {
                std::cout << "ligne 1 invalide" << std::endl; 
                return 0;
            }
            a.push_back(str2int(firstligne));
        }
        for(unsigned int i = 1; i < a.size(); i++) if(!(a[i] > 0)) {
            std::cout << "Erreur pour a[" << i << "]" << std::endl; 
            return 0;
        }
        std::vector<int> b;
        found = secndligne.find(" ");
        while (found != std::string::npos) {
            if(found != 0) {
                std::string secndstr = secndligne.substr(0, found);
                if(!valide(secndstr)) {
                    std::cout << "ligne 2 invalide" << std::endl; 
                    return 0;
                }
                b.push_back(str2int(secndstr));
            }
            secndligne = secndligne.substr(found+1);
            found = secndligne.find(" ");
        }
        if(secndligne.size() != 0) {
            if(!valide(secndligne)) {
                std::cout << "ligne 2 invalide" << std::endl; 
                return 0;
            }
            b.push_back(str2int(secndligne));
        }
        if(b[0] < 0) {std::cout << "Erreur pour b[0]" << std::endl; return 0;}
        for(unsigned int i = 1; i < b.size(); i++) if(!(b[i] > 0)) {
            std::cout << "Erreur pour b[" << i << "]" << std::endl; 
            return 0;
        }
        if(a.size() < b.size()) {std::cout << "Nombre insuffisant de a[i] " << std::endl; return 0;}
        std::cout << "a[i] successifs : ";
        for(unsigned int i = 1; i < b.size(); i++) std::cout << " " << a[i];
        std::cout << std::endl;
        std::cout << "b[i] successifs : ";
        for(unsigned int i = 0; i < b.size(); i++) std::cout << b[i] << " ";
        std::cout << std::endl;
        for(unsigned int i = 0; i < b.size(); i++) {
            std::cout << "r202duite " << i << " : ";
            reduite(i, a, b); 
            std::cout << std::endl;
        }
        return 0;
    }
    else {
        std::cout << "Erreur de lecture du fichier" << std::endl;
        return 0;
    }
}
      

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.