IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Approximation de pi


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2013
    Messages : 7
    Par défaut Approximation de pi
    Bonjour tous le monde

    Bon je suis nouveau au domaine de programmation
    J'ai cherché partout mais je ne trouve toujours pas une solution a mon problème :
    Il y a différentes façons de calculer π en mathématique. L’une d’elle est la méthode des séries infinies, on vous demande de calculer π en utilisant la série ci-dessous :
    π = 4Σ((-1)k/(2k+1)) ; k= 0, k  ∞
    et en vérifiant votre résultat contre 3.14159. Afficher la valeur de k pour obtenir le résultat
    J'ai réussi à écrire ce code, mais je suis sure qu'il n'est pas correct : j ai vraiment besoin d'aide et merci d'avance

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include<iostream>
    #include<cmath>
    #include<iomanip>
     
    using namespace std;
     
    int main (void)
    {
    	double puiss(1) , terme(1) , division , somme ,epsilon , pi , valeur;
     
    	int k , i;
    	cout.setf(ios::fixed);
    	epsilon = 0.00001;
    	somme = 0;
    	k = 0;
    	do
    	{
    		k++ ;
    		puiss = puiss * (-1) ;
    		terme = 2*k +1 ;
    		division = puiss / terme;
    		for ( i =1 ; i <= k ; i++)
    			somme += division ;
    		pi = 4* somme ;
    		valeur = fabs( 3.14159- pi );
    	}
    	while( valeur < epsilon );
    	cout << k << endl;
    	cout << setw(7) << setprecision(5) << pi << endl;
    	return 0;
    }

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Bonjour et bienvenue sur le forum

    J'ai réussi à écrire ce code, mais je suis sure qu'il n'est pas correct
    Pourquoi dis tu cela ?
    Tu as eu un bug ? Il faut le donner
    Tu as eu un résultat incorrect ? Il faut le donner aussi

    En C++, prend l'habitude de déclarer une variable par ligne, de ne le faire que lorsque tu en as besoin et de l’initialiser tout de suite. Utilise const pour les constantes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const double epsilon = 0.00001;
    int k = 0;
    (...)
    const double terme = 2*k +1;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for ( i =1 ; i <= k ; i++)
        somme += division;
    Ce que tu fais s'appelle une multiplication...
    Je suppose que ce n'était pas ça que tu voulais faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while( valeur < epsilon );
    Tu es sur de vouloir continuer le calcul "tant que le différence est inférieure à epsilon" (et donc arrêter quand la différence est plus grande que epsilon) ?

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2013
    Messages : 7
    Par défaut
    pour les declaration t'as bien raison c'est ce que je dois faire

    Mais quand je compile ca me donne la valeur

    k=1 et pi = -1.3333

    mais moi j'ai besoin de trouvé le k pour que pi sois egale a 3.14159 je pense pas que j'ai erreur dans le epsilon et l'affichage vers la fin .. mais je sais que j'ai foiré quelque part dans les somme et division ce problème m'a pris deux jours mais toujours aucun résultat j'arrive juste pas a trouvé l'erreur

    et pour la dernière ligne de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while( valeur < epsilon );
    quand j essaye l'inverse rien ne s,affiche j'imagine que cava vers des calcul infini

    Merci pour votre réponse rapide

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Oui, le calcul implémenté n'est pas le même que la formule donnée.
    Méthode pour résoudre le problème : prend une feuille de papier et un crayon et déroule la formule pour k=0, k=1, k=2, etc. Exécute ensuite ton algorithme sur la feuille de papier, en notant pour chaque ligne de ton code la valeur prise par tes variables.
    Tu trouveras ce qui est différent entre les 2

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2013
    Messages : 7
    Par défaut
    ca c'est une leçon que tu ma donné merci

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Ce qui veut dire que tu as réussit à résoudre ton problème ?

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2013
    Messages : 7
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include<iostream>
    #include<cmath>
    #include<iomanip>
     
    using namespace std;
     
    int main (void)
    {
    	const double epsilon = 0.0009;
    	const double pi1 = 3.14159;
    	int k = 0 ;
    	double somme = 0.0;
    	double pi2 =0.0;
    	double val=0.0;
    	cout.setf(ios::fixed);
     
    	while ( fabs(val) <= epsilon )
    	{
    		somme += ((pow(-1.0, k)/(2*k+1))) ;
     
    		val = pi1 - 4*somme;
    			k++;
    	}
    	pi2 = 4*somme;
    	cout << k << endl;
    	cout << setw (7) << setprecision(5) << pi2 <<endl;
    	return 0;
    }
    Bon j'en peux plus la hahaha ca commence a devenir chiant

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Tu n'es plus très loin... D'ailleurs, une autre méthode pour compléter l'étude au crayon ou papier est d'exécuter le code sous débogueur, afin de voir ce qu'il fait vraiment (c'est comme ça que j'ai vu les soucis dans ton code).

    Ta condition de boucle est toujours mauvaise : Tu vas continuer tant que ton écart sera inférieur à epsilon, c'est à dire que tu vas t'arrêter très vite...

    Par contre, une fois ta condition d'arrêt corrigée, tu va te rendre compte d'un autre problème : Ton écart est initialisé à 0 (quand on te disait d'initialiser au plus vite, c'est initialiser avec la bonne valeur, pas une valeur arbitraire dénuée de sens), c'est à dire qu'à la première évaluation la boucle va s'arrêter : Initialise le donc à une grande valeur arbitraire, ou à double val=pi1 - 4*somme;. Mieux: remet une boucle do/while : C'est bien à la fin de chaque cycle que tu veux évaluer ta condition.

    Ayant fait ça, tu auras un programme qui marchera.

    Mais qui me semble mauvais...

    Quel intérêt de calculer pi si pour ça on a besoin dans l'algorithme de la valeur de pi... Je pense que l'énoncé est plus de calculer pi indépendamment, et d'utiliser la valeur fournie lors du test unitaire de ta fonction, et non comme condition d'arrêt de ta boucle. Quand donc s'arrêter ? Et bien, chaque terme de la série est plus petit que le précédent. Donc quand le nouveau terme de la série est inférieur à un certain seuil, le nombre ne devrait plus trop bouger...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2013
    Messages : 7
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include<iostream>
    #include<cmath>
    #include<iomanip>
     
    using namespace std;
     
    int main (void)
    {
    	const double epsilon = 0.00001;
    	const double pi1 = 3.14159;
    	int k = 0 ;
    	double somme = 0.0;
    	double pi2 =0.0;
    	double val=pi1 - 4*somme;
    	cout.setf(ios::fixed);
     
    	do
    	{
     
    		somme += ((pow(-1.0, k)/(2*k+1))) ;
    		k++;
    	}
    	while ( (fabs(val) <= epsilon) && (somme <= (pi1/4)));
    	pi2 = 4*somme;
    	cout << k << endl;
    	cout << setw (7) << setprecision(5) << pi2 <<endl;
    	return 0;
    }
    ici j ai ajouté la condition mais toujours rien si je change
    et je met plus grand ça va vers des calcul infini je n'ai aucune réponse je n ai jamais eu de tel problèmes avec des exercices mais la ça commence a devenir un peu dure

  10. #10
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 962
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 962
    Par défaut
    Hoa,

    Un des problèmes avec ce genre de calcul, c'est que les approximations dues à la représentation des réels pour l'ordinateur conduisent rapidement à la divergence des calculs, et il est donc difficile de s'arrêter en fonction d'un écart prédéfini.

    Une solution souvent adoptée est plutôt de comparer les écarts successifs entre deux (ou plus) pas de calcul : on continue tant que le nouvel écart est inférieur à celui du tour précédent, OU devient inférieur au maximum fixé.


  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2013
    Messages : 7
    Par défaut
    olala je n'ai rien compris de cela je suis encore débutant l'ami hahah

  12. #12
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par Rho10
    Afficher la valeur de k pour obtenir le résultat
    Je crois que le but de l'exercice est d'avoir une idée du nombre d'itération nécessaire pour réussir à avoir une valeur avec une précision fixée. Dans ces condition, la comparaison avec une valeur donnée de Pi peut se comprendre

    Idem pour la précision, avec des doubles et une précision ciblée de 5 chiffres après la virgule, on n'aura pas de problème d'erreur de représentation

    @Rho10
    Pour le test, tu ne prends pas le problème dans le bon sens. Tu dois réfléchir au test qui sera correct et l'utiliser. C'est pas parce que ça plante qu'il faut tester d'autres conditions, il faut plutôt regarder si tu n'as pas d'erreur ailleurs
    En plus, lorsque tu lances le programme, il s'arrête pour k = 1, donc trop vite, la condition actuelle n'est pas correcte

    Dans ton code, val n'est pas modifié dans la boucle et pourtant tu le testes dans la condition, c'est normal ?
    En plus, tu ne teste plus la différence entre la valeur calculé et la valeur attendue et la tester avec epsilon
    C'était mieux avant...

    Pour la condition somme <= (pi1/4), c'est pas faux, mais c'est pas forcement une bonne idée de faire la division à chaque boucle
    Il est facile d'éviter la division en développant le "*4" dans chaque addition :
    π = 4 Σ( (-1)^k / (2k+1) )
    <=> π = 4 * (1/1 -1/3 + 1/5 - 1/7 ...)
    <=> π = Σ( 4 * (-1)^k / (2k+1) )
    <=> π = 4 *1/1 - 4*1/3 + 4*1/5 - 4*1/7 ...)
    Pour t'aider à débuter le code, tu peux aussi ajouter un cout dans la boucle, qui afficher les intermédiaires de calculs. Actuellement, si je fais ça, j'obtiens :
    k:1 terme:1.000000 pi:4.000000 error:0.858410
    Donc la première itération est correcte. Si on corrige les 2 points signalés (test d'arrêt + calcul de val), on obtient :
    k:1 terme:1.000000 pi:4.000000 error:0.858410
    k:2 terme:-0.333333 pi:2.666667 error:0.474923
    k:3 terme:0.200000 pi:3.466667 error:0.325077
    k:4 terme:-0.142857 pi:2.895238 error:0.246352
    ...
    Donc les 4 premières itérations (et le suivantes...) sont correctes. Tu n'es plus très loin de la solution...

    Pour info, il faut 23xxx itérations

  13. #13
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Idem pour la précision, avec des doubles et une précision ciblée de 5 chiffres après la virgule, on n'aura pas de problème d'erreur de représentation
    Et pourtant 3.14159 semble impossible à représenter dans un double (=3.1415899999999999 chez moi). Ce qui pose des problèmes pour savoir quand s’arrêter d'ailleurs

    @Rho10, ton epsilon est trop grand, abs(3.14159 - 3.141581) < 0.00001 mais tu n'as pas le bon nombre de chiffres significatifs corrects.

    Et tu devrais faire un k--; après être sorti de ta boucle, k sera trop grand de 1 là. (Tu fais le calcul pour k == n, puis tu l'incrémente, donc une fois sorti de ta boucle t'as k == n+1)

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Prochaine étape : réaliser l'exercice en métaprogrammation.

  15. #15
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    J'avais oublié de répondre à Iradrille

    Citation Envoyé par Iradrille Voir le message
    Et pourtant 3.14159 semble impossible à représenter dans un double (=3.1415899999999999 chez moi). Ce qui pose des problèmes pour savoir quand s’arrêter d'ailleurs
    Le fait que 3.14159 n'est pas représentable exactement n'est pas problématique ici. On ne teste par l'égalité, mais que la constante est supérieure à la valeur calculée. On aura forcement un moment où l'epsillon calculé sera supérieur à la constante puis deviendra inférieure, même si l'égalité n'est vérifiée à aucun moment

  16. #16
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288

Discussions similaires

  1. Approximation foireuse
    Par TonyEgg62 dans le forum C++
    Réponses: 8
    Dernier message: 26/04/2006, 16h43
  2. [MySQL] Implémenter une fonction de recherche approximative
    Par Chromatic dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 28/02/2006, 11h54
  3. [ImageMagick] Détection des couleurs approximative d'une image ?
    Par SkyDev dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 18/01/2006, 14h17
  4. probleme requete recherche approximative
    Par Immo dans le forum Langage SQL
    Réponses: 5
    Dernier message: 04/08/2005, 16h18
  5. [Astuce] Approximation de racines carrées
    Par Smortex dans le forum Assembleur
    Réponses: 16
    Dernier message: 18/05/2004, 06h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo