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

avec Java Discussion :

Bug ou pas bug !?


Sujet :

avec Java

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Octobre 2013
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Bug ou pas bug !?
    Bonjour à tous,

    Je commence l'étude de java et je suis tombé sur un comportement de Java qui me semble un peu bizarroïde.
    (pour info, je bosse sur éclipse sous windows 8 avec JavaSE 1.7)


    Si des "bons" on une explication, je suis preneur!

    Je me permet de vous soumettre ce simple code qui montre ce qui chez moi me semble délirer.
    Si vous pouviez le lancer pour voir si vous avez le même comportement que chez moi

    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
     
    public static void main(String[] args)
    	{
    		double a1=1.055D;
    		double a2=0.001D;
    		double a3=a1+a2;
    		System.out.println("a2 = "+a2);		
    		System.out.println("a1 = "+a1);	
    		System.out.println("a3 = "+a3);		
    		System.out.println();
    		System.out.println("les 5 lignes suivantes sont sensées afficher les mêmes valeurs!!!");
    		System.out.println(1.056D);
    		System.out.println(1.055+0.001D);	//d'où peut bien venir
    		System.out.println(a1+0.001D);		//ce qui me semble
    		System.out.println(a1+a2);			//être vrai un bug de 
    		System.out.println(a3);				//		JAVA
    		System.out.println();
    		System.out.println(a3+a3);			//comment faire confiance à ça?
    		System.out.println();
     
     
    		System.out.println(a1+0.002D);
    		System.out.println(a1+0.003D);
    		System.out.println(a1+0.004D);
    		System.out.println(a1+0.005D);
    		System.out.println(a1+0.006D);
    		System.out.println(a1+0.007D);
    		System.out.println(a1+0.008D);
    		System.out.println(a1+0.009D);
     
    		System.out.print("Je trouve que ça craint! Pas vous?");
     
    	}
    Voilà ma sortie console :

    a2 = 0.001
    a1 = 1.055
    a3 = 1.0559999999999998

    les 5 lignes suivantes sont sensées afficher les mêmes valeurs!!!
    1.056
    1.0559999999999998
    1.0559999999999998
    1.0559999999999998
    1.0559999999999998

    2.1119999999999997

    1.057
    1.0579999999999998
    1.059
    1.0599999999999998
    1.061
    1.0619999999999998
    1.063
    1.0639999999999998
    Je trouve que ça craint! Pas vous?

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Les doubles et floats en java ne sont pas des types qui stockent une valeur exacte (c'est dû à la façon de stocker, norme IEEE 754), mais une approximation.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    T'aurais pu essayer les autres langages avant de hurler au bug dans Java. Tous les langages gèrent les flottants de cette façon, les calculs flottants sont toujours approchés.
    Ouais, on peut trouver que ça craint, mais on fait avec. De toute façon on a pas le choix, il y a pas de formule magique : les ordinateurs c'est basé sur le binaire et puis c'est tout.

    Concernant la confiance à y porter, il y a deux solutions :
    - la plus courante, un DecimalFormat pour restreindre le nombre de décimales affichées : tu n'as pas besoin d'une précision à 16 décimales, c'est juste la conversion standard double => String de Java, prévue plus pour les besoins de développement que pour être affiché à l'utilisateur final.
    En te limitant à, par exemple, 5 décimales, tu auras tous les résultats à 1.056 comme attendu.
    - BigDecimal, une classe pour représenter les nombres décimaux en précision absolue au lieu de virgule flottante. Mais forcément, les performances sont infiniment moins bonnes.

    Pour information la cause est la suivante : beaucoup de nombres décimaux (comme 0.001 ou 1.055 ou 1.056) n'existent pas en représentation flottante. Lorsque tu le tapes dans ton programme, le compilateur en prend une valeur approchée. En faisant des calculs approchés sur des valeurs approchées, on retombe pas forcément sur les mêmes égalités qu'en les faisant des calculs exacts sur des valeurs exactes, c'est normal.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Les nombres à virgule flottante sont approximés, c'est la norme, dans tous les languages, et c'est comme ça directement dans le CPU.
    Ton problème ici, il viens surtout du fait que tu passe ton temps à passer de base 2 à base 10 et vis versa.

    En base deux, on stocke des puissance des 2 et des puissance de 1/2
    En base 10 on stocke des puissance de 10 et des puissance de 1/10

    Alors on peux passer sans aucun problème d'une somme de puissance de 2 à une somme de puissance de 10 et vis versa.
    Mais on ne peux pas passer d'une somme de puissances de 1/2 à des puissances de 1/10

    Ainsi, 0.1 en base 10 s'écrit 0.0001100110011001100110011001100110011......... à l'infini.
    Ce n'est pas stockable, quelle que soit la taille de la variable.

    Et donc tu fais tes calculs en base 2 mais ensuite tu les affiche en base 10, et c'est comme ça que tu te retrouve avec du 99999999999999

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Octobre 2013
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Merci pour vos réponses fulgurantes!

    OK, pas bug : c'est comme ça que ça fonctionne en interne.

    thelvin, suite à ta remarque un peu acerbe(on sent en toi un pur défenseur de Java ), j'ai refais la même chose en C++ et j'obtiens l'affichage que j'attendais.
    Certe, en allant voir mes variables en débug, je m’aperçois que leurs stockages ne sont que des valeurs approchées, mais au moins, l'arrondi est fait pour l'affichage dans la console!

    J'aurai préféré avec Java ne pas avoir a traiter cet affichage qui me déplait mais ça aura au moins eu l'avantage de me faire me pencher sur la question.

    Encore merci.

    Je passe en résolu.
    (mais j'y reviendrai avec ce qui m'a amené à cette constatation, à savoir un arrondi que je n'aime pas sur la 16ème décimale.)

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par wyzman Voir le message
    thelvin, suite à ta remarque un peu acerbe(on sent en toi un pur défenseur de Java ), j'ai refais la même chose en C++ et j'obtiens l'affichage que j'attendais.
    Certe, en allant voir mes variables en débug, je m’aperçois que leurs stockages ne sont que des valeurs approchées, mais au moins, l'arrondi est fait pour l'affichage dans la console!
    Non, ma remarque aurait été la même avec tous les langages, on me voit partout dire la même chose, peu importe que ce soit Java ou autre. Ce dont je suis un défenseur, c'est de travailler un peu avant de râler sans rien faire. En l'occurrence, vérifier d'abord si les langages font autre chose avant d'accuser un langage précis ne me semblait pas difficile... Mais penchons-nous là-dessus.

    Ta remarque selon laquelle pas mal de langages n'ont pas de conversion double => string pour le développeur, et obligent à passer par des printf ou similaires prévus pour l'utilisateur final, est pertinente. Effectivement, en faisant le même test sur d'autres langages, c'est pas évident de voir la même chose. Je retiens pour la prochaine fois.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. bug ou pas bug?
    Par ABN84 dans le forum Internet
    Réponses: 1
    Dernier message: 27/06/2009, 18h00
  2. Bug ou pas bug?
    Par Menuki dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 10/12/2008, 16h57
  3. bug (ou pas bug) avec des nombres décimaux
    Par cyberyan dans le forum Langage
    Réponses: 7
    Dernier message: 15/09/2008, 17h39
  4. FB: DB vide, impossible de connecter : Bug ou Pas Bug ?
    Par Rica dans le forum Connexion aux bases de données
    Réponses: 1
    Dernier message: 14/05/2005, 11h15

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