L'addition et la soustraction de doubles donnent des résultats étranges [dupliquer]

cette question a déjà une réponse ici:

donc quand j'ajoute ou soustrait en Java avec des Doubles, ça me donne des résultats étranges. En voici quelques-uns:

si j'ajoute 0.0 + 5.1 , ça me donne 5.1 . C'est correct.

si j'ajoute 5.1 + 0.1 , il me donne 5.199999999999 (le nombre de répéter 9 peut être éteint). C'est faux.

si je soustrais 4.8 - 0.4 , il me donne 4.39999999999995 (encore une fois, la répétition 9 s peut être éteint). C'est faux.

au début je pensais que c'était seulement le problème d'ajouter des doubles avec des valeurs décimales, mais j'avais tort.

5.1 + 0.2 = 5.3
5.1 - 0.3 = 4.8

maintenant, le premier nombre ajouté est un double enregistré comme une variable, bien que la deuxième variable saisit le texte d'un JTextField . Par exemple:

//doubleNum = 5.1 RIGHT HERE
//The textfield has only a "0.1" in it.
doubleNum += Double.parseDouble(textField.getText());
//doubleNum = 5.199999999999999
24
demandé sur BartoszKP 2013-03-26 01:55:17

2 réponses

En Java, double valeurs IEEE nombres en virgule flottante . A moins qu'elles ne soient une puissance de 2 (ou des sommes de puissances de 2, par exemple 1/8 + 1/4 = 3/8), elles ne peuvent pas être représentées exactement, même si elles ont une grande précision. Certaines opérations à virgule flottante aggraveront l'erreur d'arrondi présente dans ces nombres à virgule flottante. Dans les cas que vous avez décrits ci-dessus, les erreurs à virgule flottante sont devenues suffisamment importantes pour apparaître dans la sortie.

peu importe la source du nombre, qu'il s'agisse de séparer une chaîne d'un JTextField ou de spécifier un double littéral -- le problème est hérité de la représentation en virgule flottante.

Solutions de contournement:

  • arithmétique, puis convertir en décimal:

    (double) (51 + 1) / 10
    (double) (48 - 4) / 10
    
  • Utilisation BigDecimal 151980920"

  • si vous devez utiliser double , vous pouvez réduire les erreurs à virgule flottante avec L'algorithme de sommation de Kahan .

25
répondu rgettman 2013-03-25 22:09:23

en Java, les doubles utilisent IEEE 754 arithmétique flottante (voir cet article Wikipedia), qui est intrinsèquement inexacte. Utilisez BigDecimal pour une précision décimale parfaite. Pour arrondir à l'impression, en acceptant simplement" assez bonne précision", utiliser printf("%.3f", x) .

2
répondu raptortech97 2013-03-25 21:59:43