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 :

Pr�cision en C++


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut Pr�cision en C++
    Bonjour, je d�veloppe un programme de calcul matriciel.
    Je m'aide de maple pour v�rifier mes resultats.
    Cependant, pour certains calculs j'obtiens des r�sultats pour le moins �tranges.

    Petit exemple :
    A=
    0 1 1 1
    0 -2 -1 1
    0 -1 1 0
    -1 1 0 -1

    Inv(A) =
    -0.4 -0.6 -0.2 -1
    0.2 -0.2 -0.4 0
    0.2 -0.2 0.6 0
    0.6 0.4 -0.2 0
    Si je fais les op�rations � la main je trouve bien :
    A.Inv(A) =
    1 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 1

    par exemple :
    (1;1) => 1 = 0*(-0.4) + 1*(0.2) + 1*(0.2) + 1*(0.6)
    (3;2) => 0 = 0*(-0.6) + (-1)*(-0.2) + 1*(-0.2) + 0*(0.4)
    Pour l'instant pas de soucis
    Sauf que quand c'est mon programme qui fait le calcul j'obtient :
    A.Inv(A) =
    1 0 5.55112e-17 0
    0 1 -5.55112e-17 0
    0 0 1 0
    0 5.55112e-17 0 1
    et sur maple :


    Donc, premi�re conclusion : Vive le calcul � la main
    Et deuxi�me... Qu'est ce qu'il se passe ici ?

    Je dois avouer que je ne sais pas d'ou viens l'erreur, si n�cessaire je peux montrer mon code, mais je ne suis pas sur que l'erreur vienne de celui-ci ...

    Enfin si quelqu'un a une id�e, je suis preneur !

    Merci d'avance

    PS: je viens de voir que pour des matrices plus petites �a ne le fait jamais et la probabilit� d'erreur augmente avec la taille de la matrice ...

  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

    Il n'y a pas d'erreur (a priori), c'est juste un probl�me de repr�sentation des nombres r�els en informatique. Lorsque tu as 5.55112e-17, c'est � dire 0,000000...000555 (avec 17 z�ros), on peut consid�rer que �a fait... 0
    Donc A.inv(A) est bien :
    1 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 1
    Le mieux est probablement d'arrondir les chiffres lors de l'affichage � quelques d�cimales (1 ou 2)

  3. #3
    Membre exp�riment� Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    D�cembre 2005
    Messages
    170
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activit� : Amateur

    Informations forums :
    Inscription : D�cembre 2005
    Messages : 170
    Par d�faut
    Il n'y a pas d'erreur, mais les types a virgule flottante (float, double) ne sont pas pr�cis. Tu auras r�guli�rement des erreurs dans le genre, il faut savoir les anticiper, elles sont in�vitables.
    Mais franchement, a 10^-17, ca devrait le faire.

  4. #4
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut
    D'accord, dans ce cas, dans ma classe, il est pr�f�rable que je fasse l'arrondi de quelle mani�re ?

    Edit: En plus, je ne vois pas pourquoi maple fait aussi l'erreur, alors que ce logiciel fait des calculs tr�s pr�cis je trouve aussi des approximations de ce genre ...

  5. #5
    Membre �m�rite
    Avatar de Ekleog
    Homme Profil pro
    �tudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par d�faut
    Plusieurs solutions :

    Soit un cast vers l'entier le plus proche, si il est vraiment proche :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    double my_round(double value) {
       static const double epsilon = 1e-16; // A definir comme tu preferes
       const int rounded = static_cast<int>(value);
       if (v - rounded > 0.5) ++rounded;
       // rounded contient l'entier le plus proche. Il est aussi possible d'utiliser std::round de <cmath> pour faire ça, pour ce message je n'ai simplement pas pris le temps de vérifier le prototype exact.
       double error = rounded - value;
       if (-epsilon < error && error < epsilon) // Si on est proche de l'entier le plus proche
          return rounded; // On arrondit vers lui
       else // Sinon
          return value; // On ne change rien
    }
    Soit on fait du calcul formel, qui a l'avantage d'�tre infiniment pr�cis (autant que le calcul � la main sans arrondi, quoi) -- mais l�, bon courage !

  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
    Lors de l'affichage avec cout, tu peux pr�ciser la pr�cision souhait�e :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    double f = 3.14159;
    cout.unsetf(ios::floatfield);            // floatfield not set
    cout.precision(5);
    cout << f << endl;
    voir http://www.cplusplus.com/reference/i...ase/precision/

    Citation Envoy� par Ekleog Voir le message
    Plusieurs solutions :

    Soit un cast vers l'entier le plus proche, si il est vraiment proche :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    double my_round(double value) {
       static const double epsilon = 1e-16; // A definir comme tu preferes
       const int rounded = static_cast<int>(value);
       if (v - rounded > 0.5) ++rounded;
       // rounded contient l'entier le plus proche. Il est aussi possible d'utiliser std::round de <cmath> pour faire ça, pour ce message je n'ai simplement pas pris le temps de vérifier le prototype exact.
       double error = rounded - value;
       if (-epsilon < error && error < epsilon) // Si on est proche de l'entier le plus proche
          return rounded; // On arrondit vers lui
       else // Sinon
          return value; // On ne change rien
    }
    Soit on fait du calcul formel, qui a l'avantage d'�tre infiniment pr�cis (autant que le calcul � la main sans arrondi, quoi) -- mais l�, bon courage !
    Il vaut mieux utiliser les fonctions d'arrondis, non ?
    floor et ceil

  7. #7
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut
    Ekleog : peux-tu d�tailler un peu cette fonction s'il te plait ? Parce que j'aimerai n'utiliser que des fonctions "handmade"

    gbdivers : en fait c'est surtout la valeur qui m'interesse, l'affichage apr�s si la valeur est "exacte" (enfin si �a existe ) devrait aller

  8. #8
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Bonjour,

    1/ Les arrondis ca se fait uniquement sur l'affichage. Les incertitudes de mesure/calcul ca se d�termine/propage via des forumles, si tu commences � arrondir (*) de partout ca n'est plus possible.

    2/ A l'affichage tu peux d�cider d'arrondir � une pr�cision donn�e, mais utiliser un affichage du type A +/- delta, est tout aussi correct.

    3/ Si tu veux faire quelque chose d'efficase tu n'auras pas le choix de passer par les expressions templates, et avec ca ton probl�me va se simplifier.

    Avec les expressions templates tu vas obtenir un arbre repr�sentant ton expression, arbre que tu �valueras avec () (en g�n�ral), il est (probablement) possible lors de l'�valuation de v�rifier si il y a une expression du type mult<T,inv<U> >, et si c'est le cas de comparer (� epsilon pr�s avec un epsilon bien d�termin� : propagation des erreurs) l'�valuation de l'expression T et de l'expression U, et si elles sont "�gales" de retourner l'identit�.

    Je vais essayer de poster un code "from scratch" qui montre l'id�e, mais tu peux d�j� aller regarder du cot� de boost::proto, il donne des exemples li�s au calcul alg�brique.

    (*) Pour �tre exact, la valeur retenue doit �tre coh�rante avec l'incertitude, ca peut amener certains arrondies/troncatures, mais on arrondie pas dans le but de compenser l'incertitude.

    PS: Personnelement, si tu d�butes en C++ et que tu n'ambionnes pas quelque chose de tr�s efficase, je me contenterais de garder dans ma classe matrice quelque chose repr�sentant l'incertitude, et ferais une fonction d'affichage � une pr�cision donn�e ou alors un affichage de type A +/- delta.

  9. #9
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut
    Flob90 : c'est vrai, vu que je d�bute je n'ai pas compris grand chose aux templates
    je pense que je ne vais pas me compliquer trop la vie, un e-17 �a reste potable et au moment de mon affichage je me d�brouillerai

    cela dit, par rapport � la propagation d'incertitude je viens de voir que pour une matrice 10*10 j'avais des "0" estim�s qui valaient apr�s calcul � 0,7 ou un chiffre beaucoup plus grand qu'avant... ce qui est tr�s facheux!

  10. #10
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    C'est �trange, les incertitudes grandisent en se propagant, mais pour passer de 10^-17 � 0.1, il faut �norm�ment d'op�rations. Mapple aussi te donne 0.7 ? Dans ce cas c'est peut-�tre toi qui a calcul� un 0 alors que ca n'en �tait pas un.

  11. #11
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut
    Oui dans l'ensemble Maple me donne a peu pr�s les m�mes valeurs que mon programme, je suis en train de le retaper voir si je n'ai pas laiss� une instructions qui merdouille quelque part.

    En fait comme le calcul matriciel �a peut se faire en r�cursif pour certaines op�rations il arrive de trouver des calculs assez longs en effet

  12. #12
    Membre Expert

    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2004
    Messages
    1 391
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Doubs (Franche Comt�)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 1 391
    Par d�faut
    Oui, sauf que pour passer de 10^-17 � 0.1, il faut, environ, 10^32 op�rations, je doute que tu fasses autant d'op�rations pour calculer un coefficient de la matrice.

  13. #13
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut
    Pas faux, donc c'est bien une erreur ailleurs ! Je vais rev�rifier tout �a, merci de me l'avoir montr� !

    edit : j'ai fait un ptit test des valeurs erron�es :
    -matrice 3*3 environ 1 fois sur 6 j'ai un e-15
    -pour 4*4 quasiment tout le temps du e-13
    -pour 5*5 tout le temps aussi du e-12
    -pour 6*6 du e-10
    -pour 7*7 du e-7
    -idem pour 8*8
    -pour 9*9 du e-6
    -pour 10*10 du e-5

    -pour 11*11 ma premi�re ligne est :

    -1.42729e+10
    0.000221252
    -4.24228e+10
    1.42124e+11
    -2.16188e+10
    -6.07565e+09
    4.87028e+10
    -5.93413e+09
    -1.61922e+09
    -2.31562e+10
    5.9881e+09

    le premier terme est bon, mais les autres devraient etre nuls, et l� carr�ment non

  14. #14
    Expert confirm�

    Inscrit en
    Novembre 2005
    Messages
    5 145
    D�tails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par d�faut
    Il y a des algo qui se comportent mieux. Cherche un cours d'analyse num�rique (qui est la branche qui �tudie les algos de calculs num�riques, en particulier l'effet des impr�cisions).

  15. #15
    Invit�
    Invit�(e)
    Par d�faut
    Citation Envoy� par Vaffreingue Voir le message
    -pour 11*11 ma premi�re ligne est :

    (...)

    le premier terme est bon, mais les autres devraient etre nuls, et l� carr�ment non
    Que calcules tu exactement?

    Si tu fais des sommes et des produits matriciels, sur des matrices � coefficients born�s, les r�sultats que tu observes doivent tenir � un bug. L'erreur d'arrondi n'augmente pas lin�airement avec le nombre de calculs, mais elle est toujours nettement inf�rieure � la valeur absolue des plus grands coefficients de tes matrices.

    Les choses peuvent tr�s mal tourner quand tu fais des calculs plus complexes (tout ce qui contient un m�lange d'additions et de divisions : recherches de valeurs propres, calcul de pivot, ou inversion). Dans ce cas, les erreurs peuvent s'amplifier et devenir �normes.

    En g�n�ral, cela se produit parce que tes matrices sont mal conditionn�es (c'est � dire que le rapport entre leur plus petite et leur plus grande valeur propre est grand). Ca devient intenable quand on a des matrices non inversibles (ou quasiment...). Dans ce cas, le conditionnement est infini.

    Le probl�me est malheureusement tr�s courant avec des matrices "de la vraie vie", par exemple des variances-covariances statistiques, qui sont toujours mal conditionn�es (sinon, cela voudrait dire que tous les axes de la matrice sont ind�pendants, et celle ci n'aurait aucun int�r�t). Si tu d�veloppes un programme de calcul matriciel, tu vas le rencontrer assez vite.

    Une "astuce" permettant de stabiliser les calculs consiste � ajouter � ta matrice de d�part une diagonale dont les termes sont tr�s petits (1e-6 par exemple). Celle ci ne perturbera pas les r�sultats, mais stabilisera le calcul. Sur de petites matrices (quelques dizaines de lignes et de colonnes), c'est g�n�ralement suffisant.

    Francois

  16. #16
    Membre averti
    Homme Profil pro
    �tudiant
    Inscrit en
    F�vrier 2012
    Messages
    16
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : F�vrier 2012
    Messages : 16
    Par d�faut
    Bonjour !

    Pour l'instant, je vais m'en tenir � cette solution : apr�s chaque op�ration je vais tronquer la valeur � e-6 et puis normalement �a devrait suffir pour l'instant

    Merci � vous pour vos r�ponses !

  17. #17
    Expert confirm�

    Inscrit en
    Novembre 2005
    Messages
    5 145
    D�tails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par d�faut
    Citation Envoy� par Vaffreingue Voir le message
    Bonjour !

    Pour l'instant, je vais m'en tenir � cette solution : apr�s chaque op�ration je vais tronquer la valeur � e-6 et puis normalement �a devrait suffir pour l'instant

    Merci � vous pour vos r�ponses !
    Pas une bonne idee du tout ca va vraisemblablement te causer d'autres problemes (p.e. tu ne vas pas etre capable de traiter une matrice dont tous les termes sont petits par rapport a 1e-6 et pourtant suffisemment grand pour ne jamais poser de probleme si on traite les choses comme il faut).

  18. #18
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par d�faut
    Bonsoir,

    il faut que tu choisisses si tu veux faire du calcul formel (pr�cis mais lent) ou du calcul num�rique (rapide mais impr�cis). Dans le second cas, tu ne dois jamais arrondir toi-m�me les calculs. Si tu consid�res que la pr�cision de tes calculs n'est pas suffisante, deux solutions s'offrent � toi :
    1. modifier l'algorithme pour am�liorer sa stabilit�,
    2. changer de format de flottant
    Deux remarques par ailleurs :
    i. on n'inverse jamais une matrice : on la factorise puis on inverse les facteurs,
    ii. le r�sultat obtenu avec la matrice 11x11 est suspect. Es-tu s�r que ta matrice est bien inversible?
    N'h�site pas � fournir ta matrice et le code source si besoin.

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Pr�cision sur Oracle 9iAS r2
    Par Patmane dans le forum Oracle
    R�ponses: 9
    Dernier message: 18/03/2007, 04h41
  2. [3DNow !] Pr�cision
    Par delire8 dans le forum x86 32-bits / 64-bits
    R�ponses: 11
    Dernier message: 19/02/2004, 19h10
  3. [EJB]Pr�cision de la datasource (Mysql)
    Par cameleon2002 dans le forum JBuilder
    R�ponses: 2
    Dernier message: 11/09/2003, 17h55
  4. R�ponses: 8
    Dernier message: 13/01/2003, 17h45
  5. Timer de pr�cision
    Par guigui dans le forum MFC
    R�ponses: 1
    Dernier message: 04/12/2002, 15h21

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