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

Langage Java Discussion :

Enigme du type Double


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Février 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 21
    Par défaut Enigme du type Double
    Bonjour à tous,

    Je crois que cette curiosité n'est pas spécifique à JAVA mais je la pose quand même :

    pourquoi :
    System.out.println(100.0*1.1);

    donne :

    110.00000000000001

    ??

    que faire pour avoir le bon résultat?

    A+

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,



    Les nombres flottants correspondent à des approximations, car il est tout bonnement impossible de représenter tous les nombres flottants sur une zone mémoire limité... car on peut toujours rajouté une décimales

    Essayes de représenter tous les nombres flottant entres 0.0 et 1.0 et tu verras le problème


    Donc on a affaire à des approximations sur la partie flottante, basé sur une norme (IEEE 754) intégré dans tous les processeurs actuels. Ainsi chez moi 1.1 vaut en réalité 1.100000000000000088817841970012523233890533447265625.

    Le problème étant qu'avec certains calcul cette approximation peut s'accumuler et amener des erreurs. Il faut ainsi arrondir les résultats pour éviter les erreurs les plus courantes.



    Mais si on veut un calcul précis, il faut utiliser des BigDecimal (ce qui implique également un code plus lourd ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println( new BigDecimal("1.1").multiply(new BigDecimal("100.0")) );
    Attention à ne pas initialiser les BigDecimal avec un double ou un float, car sinon on conserve l'approximation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println( new BigDecimal(1.1) ); // 1.100000000000000088817841970012523233890533447265625

    a++

  3. #3
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 909
    Billets dans le blog
    54
    Par défaut
    Et dans le cas ou tu preferes rester avec des types de base, le probleme de l'affichage se resoud en utilisant un formatteur pour l'affichage. Voir NumberFormat et DecimalFormat (ceci ne fait que cacher le manque de precision, le probleme est toujours present).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  4. #4
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 969
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 969
    Par défaut
    Hie,
    Citation Envoyé par adiGuba Voir le message
    Ainsi chez moi 1.1 vaut en réalité 1.100000000000000088817841970012523233890533447265625.
    Non, tu obtiens cet affichage.

    Le plus grand type flottant en Java, le double, est codé en 64 bits, dont 50 pour la mantisse, soit au mieux 16 à 17 chiffres significatifs, or tu en donnes 53, soit plus de 3 fois plus.

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par droggo Voir le message
    Hie,

    Non, tu obtiens cet affichage.

    Le plus grand type flottant en Java, le double, est codé en 64 bits, dont 50 pour la mantisse, soit au mieux 16 à 17 chiffres significatifs, or tu en donnes 53, soit plus de 3 fois plus.

    mmm 2^-50 donne ceci:


    8.8817841970012523233890533447265625E-16
    la 50ème décimale binaire de la mantise nécessite donc 52 décimales en base 10

    la transformation flottant -> décimal peut toujours etre faite de manière exacte, car on peut représenter en décimal toutes les puissance négatives de 2. Par contre, on ne peux pas représenter en somme puissance de 2 tous les nombres décimaux.

  6. #6
    Expert confirmé

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

    Alors j'en conclu que le calcul est effectué avec un type plus grand que double, car 2^50 fait 1125899906842624, soit environ 10^17, ce qui est donc la limite en chiffres décimaux pour ce type.

  7. #7
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    il ne s'agit pas de 2^50 mais de 2^-50 !


    c'est pas parce que tu a besoin de n chiffre pour répresenter un nombre X que tu as beosin de ~n chiffre pour représenter 1/n


    et en l'occurence 1/1125899906842624 donne bien

    8.881784197001252323389053344726562500000000000000000000000000000000000000000000000000E-16


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class Test {
        public static void main(String[] argv){
           BigDecimal bd = new BigDecimal("1");
           bd=bd.setScale(100);
           System.out.println("1/2^50="+bd.divide(new BigDecimal("1125899906842624""),BigDecimal.ROUND_UNNECESSARY));
        }
    }
    donc les chiffre significatif d'adiguba sont bel est bien corrects pour représenter exactement le flottant
    C'est juste que d'habitue on arrondi au quelques décimale pour garder la cohérence avec la mathématique en base 10

Discussions similaires

  1. Conversion de type double en texte
    Par CoachMac dans le forum C
    Réponses: 17
    Dernier message: 14/10/2006, 19h29
  2. [Socket] Send/Recv type double sur architectures différentes
    Par nicolas.pied dans le forum Réseau
    Réponses: 4
    Dernier message: 31/03/2006, 20h33
  3. Variable de type double
    Par Linaa dans le forum C
    Réponses: 16
    Dernier message: 21/01/2006, 13h04
  4. arrondi avec type double
    Par la drogue c'est mal dans le forum MFC
    Réponses: 6
    Dernier message: 08/04/2005, 17h51
  5. [LG]Convertir le type double en string
    Par @tom@ dans le forum Langage
    Réponses: 8
    Dernier message: 18/01/2004, 19h20

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