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 :

Méthode de Newton pour le calcul de l'inverse d'un réel


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Arabie Saoudite

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 51
    Par défaut Méthode de Newton pour le calcul de l'inverse d'un réel
    Bonsoir à tous,

    J'ai défini une classe 'function' ainsi qu'une classe 'polynomial' qui en hérite. Voici leurs interfaces :
    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
    32
    33
    34
    35
    36
    37
    #include <iostream>
    #include <cmath>
    #include <assert.h>
     
    using namespace std;
     
    class function {
     
    public:
        function(){};
        virtual function* clone()const=0;
        virtual float operator()(float x)const=0; //gives the image of a number by the function
        virtual function* derivative()const=0;
        virtual float inverse(float y)const=0; 
        virtual ~function(){}   
    };
     
     
     
    class polynomial : public function {
    protected:
        int degree;
    private:
        float *coefficient;
    public:
        //polynomial(){degree=-1;} //default constructor
        polynomial(int d);
        virtual~polynomial();
        virtual function* clone()const;
        int get_degree()const;
        float operator[](int i)const; //reads the coefficient number i
        float& operator[](int i); //updates the coefficient number i
        virtual float operator()(float x)const; 
        virtual function* derivative()const;
        virtual float inverse(float y)const; 
     
    };
    J'ai codé toutes les fonctions liées à 'polynomial'. Elles ont l'air de bien marcher jusqu'ici, sauf pour la méthode 'inverse'. Elle est basée sur la méthode de Newton qui donne le zéro d'une fonction. Je l'applique dans la méthode 'inverse' à la fonction x->f(x)-y où y est fixé (c'est l'élément dont on cherche l'antécédent) et f est l'instance en cours.

    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
    float polynomial::inverse(float y)const
    {
        int i=0;
        float x0=1;
        function* deriv=derivative();
        float x1=x0+(y-operator()(x0))/(deriv->operator()(x0));
        while(i<=250 && std::abs(x1-x0)>1e-5)
        {
            x0=x1;
            x1=x0+(y-operator()(x0))/(deriv->operator()(x0));
            i++;
        }
     
        if(std::abs(x1-x0)<=1e-5) 
        {
            //delete deriv; // En dé-commentant, j'ai des erreurs de mémoire
            return x1;   
        }
     
        else    
        {
            cout<<"Maximum iteration reached in polynomial method 'inverse'"<<endl;
            //delete deriv; // idem 
            return -1;
        }
    }
    Je teste ma méthode avec le main ci dessous et il s'avère que le nombre maximum d'itérations est atteint sans obtenir un résultat. J'ai lu quelques articles en ligne et à priori la méthode de Newton marche bien et pas besoin d'un grand nombre d'itérations.
    D'un autre côté, je suis allée me documenter sur la fonction 'abs', et elle prend en considération les floats lorsqu'on inclut <cmath>.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include "function.h"
     
    int main(int argc, const char * argv[])
    {
     
        polynomial p(3);
        for(int i=0;i<=2;i++) p[i]=0;
        p[3]=1;
        cout<<"27^(1/3)="<<p.inverse(27);
        return 0;
    }
     
    //returns 27^(1/3)=Maximum iteration reached in polynomial method 'inverse' -1

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 487
    Par défaut
    Attention à la stabilité numérique de votre algorithme avec les erreurs d'arrondi dur nombre à virgule flottante.
    A l'arrache, sauf cas de besoin de performance aigüe, utilisez des double à la place de float.

  3. #3
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Arabie Saoudite

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 51
    Par défaut
    Rien n'y fait. Le nombre d'itérations est toujours atteint avant de trouver une valeur pertinente, même si j'ai converti tous les float en double.

  4. #4
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Arabie Saoudite

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 51
    Par défaut
    J'ai modifié le type de retour de la méthode 'derivative' de 'polynomial' en 'polynomial*'. Je laisse la définition exactement telle qu'elle était. Il s'avère alors que le programme est non déterministe et échoue toujours : soit il me renvoie 'Maximum itération reached', soit il me renvoie 27^(1/3)=1.
    Je doute que ce 1 est en relation avec l'itéré de départ x0 dans la méthode 'inverse', comme si x0 et x1 ne sont pas mis à jour dans la boucle while. En effet, en modifiant la valeur initiale de x0, le main me retourne toujours la nouvelle valeur avec laquelle j'ai mis à jours x0.

  5. #5
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Arabie Saoudite

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 51
    Par défaut
    J'ai ajouté quelques cout par ci par là, et me suis rendu compte que deriv->operator()(x0) ne donne pas la valeur attendue. Par exemple, quand x0 vaut 1, ça me retourne -2.68156e+154

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 487
    Par défaut
    Utilisez le débuggeur au lieu des cout tout pourris pour debugger.

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/02/2015, 19h25
  2. Programme pour méthode de Newton
    Par houred dans le forum Débuter
    Réponses: 5
    Dernier message: 02/06/2008, 11h18
  3. calcul de la racine carrée par la méthode de Newton
    Par annoussa dans le forum Algorithmes et structures de données
    Réponses: 9
    Dernier message: 02/11/2006, 11h10
  4. Réponses: 6
    Dernier message: 06/10/2005, 16h02
  5. Méthode pour du calcul partagé (urgent...)
    Par cedricB dans le forum CORBA
    Réponses: 8
    Dernier message: 24/01/2005, 19h59

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