L'addition et la soustraction de doubles donnent des résultats étranges [dupliquer]
cette question a déjà une réponse ici:
- Conserver la précision avec double en Java 20 réponses
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
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 .
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)
.