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 :

precision et très petits nombres


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut precision et très petits nombres
    Bonjour tous,

    je sais que les "double" peuvent stocker des nombres de -1e308 à 1e308 mais qu'en est il pour la precision de calcul pour des petits nombres?

    j'ai entendu que les résultats était correct à 10e-16 près, donc ca veut dire que si je fais des opérations avec des double du type 10e-29 , 10e-40 mes résultats seront faux ??

    Merci de m'éclaircir ce point s'il vous plait

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 485
    Par défaut
    N'oublie pas que tes float ou double sont codés en binaire et pas en décimal. Choisir un intervalle en base 10 est une bonne approximation, mais tu risques d'avoir quelques surprises désagréables lorsque tes nombres se rapprocheront des limites.

    Ensuite, l'exposant d'un double tient sur onze bits et est signé. Cela veut donc dire que le nombre minimum théorique (hors valeurs réservées) vaut 1,0⋅2⁻¹⁰²⁴, ce qui correspond à peu de choses près à 1,0⋅10³⁰⁸, et pas -1,0⋅10³⁰⁸, que l'on peut aussi représenter à peu de choses près.

    Par contre, un flottant, ça utilise le principe de la notation scientifique. Dès que le nombre binaire correspondant à la valeur que tu veux coder dépasse 24 bits dans un float ou 53 dans un double, tu perdras en précision.

    Tu peux également lire ces discussions :

    http://www.developpez.net/forums/d63...f/#post3744727
    http://www.developpez.net/forums/d84...on-aux-floats/

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    Excuse moi mais je suis un (grand) débutant, j'aurais besoin de plus de détails pour bien comprendre...

    Citation Envoyé par Obsidian Voir le message
    N'oublie pas que tes float ou double sont codés en binaire et pas en décimal. Choisir un intervalle en base 10 est une bonne approximation, mais tu risques d'avoir quelques surprises désagréables lorsque tes nombres se rapprocheront des limites.
    je n'ai pas bien compris cela... Un double ou float doit etre codé en binaire mais nous on lui donne un décimal et ca pose probleme car il est difficile d'écrire un décimal en binaire?

    Citation Envoyé par Obsidian Voir le message
    :
    Certains nombres finis en décimal ne le sont pas en binaire. Exemple :
    1.5d = 1.1b
    1.2d = 1.0011001100110011...b
    mes souvenir concernant cela sont loin, pourquoi 1,2 ne s'écrit pas:
    1.10 ?
    Citation Envoyé par Obsidian Voir le message
    - La mantisse d'un float tient sur vingt-trois bits et 12548.865 s'écrit 11000100000100.1101110101 en binaire (donc 24 bits). Ça veut dire que tu ne peux pas avoir une précision au millième près avec des nombres de l'ordre de 10^4 ou supérieurs.
    :
    je n'ai pas bien compris ce passage...
    Citation Envoyé par Obsidian Voir le message
    N
    Ensuite, l'exposant d'un double tient sur onze bits et est signé. Cela veut donc dire que le nombre minimum théorique (hors valeurs réservées) vaut 1,0⋅2⁻¹⁰²⁴, ce qui correspond à peu de choses près à 1,0⋅10³⁰⁸, et pas -1,0⋅10³⁰⁸, que l'on peut aussi représenter à peu de choses près.
    si j'ai bien compris l'exposant le plus petit possible pour un double est 1e-308 ?
    Citation Envoyé par Obsidian Voir le message
    Par contre, un flottant, ça utilise le principe de la notation scientifique. Dès que le nombre binaire correspondant à la valeur que tu veux coder dépasse 24 bits dans un float ou 53 dans un double, tu perdras en précision.
    53bits ca correspond à combien de chiffres en décimales? (tu peux me donner le détails pour que je comprennes?)

    merci pour ton aide

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    typiquement dans mon code je manipule des nombres de l'ordre de grandeur:
    6.5678e-40
    la precision sera à 10e-55 pres non?

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 485
    Par défaut
    Citation Envoyé par 21did21 Voir le message
    Excuse moi mais je suis un (grand) débutant, j'aurais besoin de plus de détails pour bien comprendre...
    Certainement…

    je n'ai pas bien compris cela... Un double ou float doit etre codé en binaire mais nous on lui donne un décimal et ca pose probleme car il est difficile d'écrire un décimal en binaire?
    Non. Ton décimal sera converti en binaire et stocké ainsi. Ce que je veux dire, c'est que bon nombre de scientifiques dont l'informatique n'est pas le métier principal tendent à établir d'emblée l'intervalle d'un nombre flottant entre deux puissances de dix, quitte à se laisser des marges. Or, les limites des ces nombres flottants sont des nombres « ronds » en binaire, mais pas en décimal. Donc, si un programmeur a pris d'emblée l'habitude de se référer à ces limites approximatives, il risque d'avoir des surprises lorsqu'il va les approcher.

    mes souvenir concernant cela sont loin, pourquoi 1,2 ne s'écrit pas:
    1.10 ?
    Le binaire n'est pas un format arbitraire inventé pour l'informatique comme le sont les nombres flottant IEEE en simple ou double précision. Le binaire, ce n'est rien d'autre que la base 2.

    En décimal, la « première colonne » est celle des unités, la suivante celle des dizaines, la suivante celle des centaines, et ainsi de suite. En binaire, la « première colonne » est celle des unités, la suivante celle des multiples de 2, la suivante celle des multiples de 4, celle d'après les multiples de 8, etc.

    En partant de l'autre côté, à droite de la virgule, la première colonne (donc la première décimale) est celle des dixièmes, la suivante celle des centièmes, puis celle des millième, etc.

    En binaire, donc, les chiffres à droite de la virgule sont respectivement celui des demis « ½ », puis celui des quarts « ¼ », puis celui des huitièmes, etc.

    1,11 en binaire vaut donc 1 + 0,5 + 0,25 soit 1,75 en décimal.
    1,10 en binaire vaut donc 1 + 0,5 = 1,5 et le zéro de droite est un zéro non significatif.

    Maintenant, si l'on cherche à approcher « 1,2 » :

    1b (« 1 en binaire ») = 1d (« 1 en décimal ») ;
    1,1b = 1,5d → trop grand ;
    1,01b = 1,25d → trop grand ;
    1,001b = 1,125d → ok ;
    1,0011b = 1,1875d → ok;
    1,00111b = 1,21875d → trop grand ;
    1,001101b = 1,203125d → trop grand ;
    1,0011001b = 1,1953125 → ok ;


    Dans certains cas, tu finiras par trouver le compte juste. Dans d'autre (comme ici), tu te contenteras de tourner autour sans jamais trouver une valeur exacte. C'est ton ordinateur qui, une fois la limite atteinte, procédera à un arrondi par défaut ou par excès, et en fonction de ta base.

    À noter que c'est vrai dans toutes les bases. Par exemple, en décimal, « un tiers : 1 ÷ 3 » s'écrit 0,333333… et ce nombre n'est pas un nombre fini. Par contre, en base 9, cette même valeur « 1 ÷ 3 » s'écrit exactement « 0,3 ».

    je n'ai pas bien compris ce passage...
    C'est le principe de la notation scientifique. Relis bien la discussion en entier, l'explication est tout en bas.

    À l'école, au collège, on nous apprenait souvent, en cours de physique, à représenter les grandeurs avec deux chiffres après la virgule et un exposant. Par exemple :

    « 1,43 ⋅ 10⁻⁵ »
    « 6,13 ⋅ 10³ »

    Dans le second exemple, 6,13 ⋅ 10³ vaut en fait 6130. Avec seulement deux chiffres après la virgule, tu pourras représenter 6120 ou 6140, mais pas 6131.

    si j'ai bien compris l'exposant le plus petit possible pour un double est 1e-308 ?
    Non, pour être parfaitement exact, l'exposant le plus petit sur un double est « 2⁻¹⁰²³ ». Cette valeur correspond grosso-modo à 10⁻³⁰⁸, mais ce n'est qu'une approximation.

    53bits ca correspond à combien de chiffres en décimales? (tu peux me donner le détails pour que je comprennes?)
    « bit » signifie « Binary Digit », soit « chiffre binaire ». Avec 53 bits, tu peux compter de 0 à 2⁵³-1, de la même façon qu'avec trois chiffres décimaux, tu peux compter de 0 à 10³-1, donc de 000 à 999.

    Si tu veux savoir combien cela fait, ouvre une calculatrice sur ton ordinateur :
    2⁵³ - 1 = 9.007.199.254.740.991

    Citation Envoyé par 21did21 Voir le message
    typiquement dans mon code je manipule des nombres de l'ordre de grandeur: 6.5678e-40 la precision sera à 10e-55 pres non?
    Plus que l'exposant, c'est surtout le nombre de décimales qui est important. Ici, tu utilises quatre décimales après la virgule. Cela fait donc un champ de 100.000 points (parce qu'il y a autant de combinaisons possibles de 0 à 9,9999 qu'il y en a de 0 à 99.999, soit cent mille moins 1).

    Cent mille s'écrit 11000011010100000 en binaire, soit 17 bits. Ça tient largement dans la mantisse d'un double (53 bits) et même d'un float (24 bits), même en tenant compte des imprécisions.

    Par contre, il faut se souvenir que modifier un exposant « 10 » en binaire ne se fait pas simplement : « 12 » est un nombre entier et sera donc toujours codable en binaire. Par contre, « 1,2 » ne peut pas être représenté de manière exacte, même si ton ordinateur s'arrange pour retomber sur ses pieds et te présenter une valeur aussi correcte que possible.

    Ce n'est pas un problème en soi, sauf si tu fais beaucoup de calculs entre différentes valeurs, toutes endémiquement imprécises. En principe, statistiquement, les différentes imprécisions devraient se compenser entre elles et, la plupart du temps, tu n'auras jamais d'ennuis. Mais dans certains cas, notamment lors de progressions géométriques, il se peut que les imprécisions se cumulent dans le même sens et qu'à terme, tu ne puisses plus garantir la validité des nombres que tu obtiens. Mais tu aurais le même problème avec une bête calculatrice…

    Si tu en arrives là, le meilleur moyen de s'en affranchir est de travailler avec des nombres entiers, et de gérer soi-même les ordres de grandeur en fin de calcul.

  6. #6
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par 21did21 Voir le message
    Bonjour tous,

    je sais que les "double" peuvent stocker des nombres de -1e308 à 1e308 mais qu'en est il pour la precision de calcul pour des petits nombres?

    j'ai entendu que les résultats était correct à 10e-16 près, donc ca veut dire que si je fais des opérations avec des double du type 10e-29 , 10e-40 mes résultats seront faux ??

    Merci de m'éclaircir ce point s'il vous plait
    Selon le standard IEEE 754 double précision, le plus petit nombre normalisé (2**-1022), le plus grand nombre dénormalisé est (2**-1022 - 2**-1074) et le nombre normalisé suivant est (2**-1022 + 2**-1074).

    La précision est dont de l'ordre de 2**-1074, ce qui vaut environ 5 x 10**-324.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Par défaut
    merci tous pour votre aide

    c'est vraiment tres gentil, quel super forum

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 485
    Par défaut
    Bonjour,

    Citation Envoyé par Thierry Chappuis Voir le message
    La précision est dont de l'ordre de 2**-1074, ce qui vaut environ 5 x 10**-324.
    Tu es sûr de toi pour « -1074 », ça me paraît être une valeur un peu bâtarde, surtout que onze bits permettent de coder un nombre de -1024 à +1023. Il y a l'air d'y avoir une faute sur Wikipédia…

    Citation Envoyé par 21did21 Voir le message
    merci tous pour votre aide c'est vraiment tres gentil, quel super forum
    À ton service.
    Lis aussi ceci : http://download.oracle.com/docs/cd/E..._goldberg.html

  9. #9
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Bonjour,



    Tu es sûr de toi pour « -1074 », ça me paraît être une valeur un peu bâtarde, surtout que onze bits permettent de coder un nombre de -1024 à +1023. Il y a l'air d'y avoir une faute sur Wikipédia…
    Sauf erreur de ma part, le plus petit nombre normalisé dans IEEE 754 s'écrit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    0 00000000001 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00
    l'exposant vaut 1-1023=-1022, la mantisse 2**0 et le signe est positif, ce qui nous donne 2**0 x 2**-1022

    Le plus petit nombre normalisé qui suit s'écrit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    0 00000000001 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00
    l'exposant vaut toujours 1-1023 = -1022, la mantisse (2**0 + 2**-52) et le signe est positif, ce qui nous donne 2**0 x 2**-1022 + 2**-52 x 2**-1022 = 2**-1022 + 2**(-1022-52) = 2**-1022 + 2**-1074

    L'écart entre les deux plus petits nombres normalisés est par conséquent de 2**-1074, à savoir DBL_EPSILON * 2**-1022.

    DBL_EPSILON représente la différence entre le nombre (double) 1.0 et le nombre suivant et vaut 2**-52 ~= 2.220446 x 10**-16, sur les machines où les nombres à virgules flottantes sont implantés en conformité avec le standard IEEE 754, ce qui est bien le cas de ma machine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #include <stdio.h>
    #include <float.h>
     
    int main()
    {
    	printf("DBL_EPSILON vaut %e\n", DBL_EPSILON);
     
    	return 0;
    }
    affiche:
    Code console : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    DBL_EPSILON vaut 2.220446e-16

    Par ailleurs, l'erreur entre chaque nombre dénormalisé et entre le plus grand nombre dénormalisé positif et le plus petit nombre normalisé positif vaut 2**-1022 * DBL_EPSILON = 2**-1074 ~= 5 x 10**-324.

    Peut-être que quelque chose m'échappe.... (?)

    Avec mes meilleures salutations

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 485
    Par défaut
    Ok, ok, ok ! C'est moi qui avait lu trop vite. On parle bien de précision. L'exposant minimum vaut 2⁻¹⁰²² et, donc, la plus petite décimale dans cet ordre de grandeur vaut à peu près 2⁻¹⁰⁷⁴ puisqu'elle se trouve 52 bits plus loin.

    C'est donc bien moi qui m'emmêlais les pinceaux.
    Merci pour ces précisions.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Calculs sur de très petits nombres (0-255)
    Par Kaluza dans le forum Langage
    Réponses: 11
    Dernier message: 06/04/2011, 15h13
  2. soustraction avec un très petit nombre
    Par djocin dans le forum Fortran
    Réponses: 10
    Dernier message: 13/07/2010, 08h26
  3. un nombre double très petit
    Par pipip dans le forum Langage
    Réponses: 9
    Dernier message: 27/12/2008, 20h04
  4. [langage] Erreur d'arrondi sur petits nombres
    Par Tchetch dans le forum Langage
    Réponses: 7
    Dernier message: 12/01/2005, 10h11
  5. Une unité pour gérer des très grands nombres
    Par M.Dlb dans le forum Langage
    Réponses: 2
    Dernier message: 09/09/2003, 12h07

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