** Le code de cet article est écrit en Java SE 8. ** **
Si vous comparez des variables de type double avec ==
, vous remarquerez que ce n'est pas bon avec les outils d'analyse statique, c'est un bogue.
J'étais curieux de connaître diverses choses, alors j'ai essayé de savoir comment gérer les nombres à virgule flottante (maintenant).
Si vous ne vous souciez pas des performances, utilisez Big Decimal. Si vous pouvez modifier la conception de la base de données, vous pouvez déplacer les chiffres et les gérer avec int ou long.
Tout d'abord, jetez un œil à celui-ci.
code
double doubleValue1 = 1.0d;
double doubleValue2 = 0.9d;
double resultValue = doubleValue1 - doubleValue2;
System.out.println("doubleValue1: " + doubleValue1);
System.out.println("doubleValue2: " + doubleValue2);
System.out.println(resultValue == 0.1d);
System.out.println("Résultat de la soustraction: " + resultValue);
** Résultat d'exécution **
doubleValue1: 1.0
doubleValue2: 0.9
false
Résultat de la soustraction: 0.09999999999999998
Le résultat de la soustraction est censé être excellent.
Les ordinateurs traitent les nombres en binaire.
Cependant, certaines fractions, telles que "0,9", deviennent des fractions circulaires lorsqu'elles sont exprimées en binaire. Étant donné que l'ordinateur ne peut gérer qu'un nombre fini de chiffres, il est arrondi à une valeur appropriée et une erreur se produit.
Puisqu'il est subtilement soustrait avec une valeur autre que "0,9", le résultat ci-dessus sera obtenu. Dans le système comptable, même une erreur de 1 yen peut conduire à un procès, ce qui est un gros problème.
Utilisez BigDecimal pour résoudre le problème!
code
BigDecimal bigDecimalValue1 = new BigDecimal("1.0");
BigDecimal bigDecimalValue2 = new BigDecimal("0.9");
BigDecimal bigDecimalResultValue = bigDecimalValue1.subtract(bigDecimalValue2);
System.out.println("bigDecimalValue1: " + bigDecimalValue1);
System.out.println("bigDecimalValue2: " + bigDecimalValue2);
System.out.println(bigDecimalResultValue.equals(new BigDecimal("0.1")));
System.out.println("Résultat de la soustraction: " + bigDecimalResultValue);
** Résultat d'exécution **
bigDecimalValue1: 1.0
bigDecimalValue2: 0.9
true
Résultat de la soustraction: 0.1
BigDecimal contient la valeur sous la forme de décalage de la partie fractionnaire vers la partie entière. Puisque tous les nombres entiers peuvent être représentés par des nombres binaires finis, BigDecimal peut être utilisé pour calculer et comparer avec précision les nombres à virgule flottante.
La méthode est Reportez-vous à la référence officielle.
Étant donné que BigDecimal est un type de référence, il est naturellement plus lent que les opérations de type de données de base. Allons vérifier.
code
double doubleValue1 = 1.0d;
double doubleValue2 = 0.9d;
long startDouble = System.currentTimeMillis();
//100 millions de déductions(double)
for(int i = 0; i < 100_000_000 ; i++){
double resultValue = doubleValue1 - doubleValue2;
}
long endDouble = System.currentTimeMillis();
BigDecimal bigDecimalValue1 = new BigDecimal("1.0");
BigDecimal bigDecimalValue2 = new BigDecimal("0.9");
long startBigDecimal = System.currentTimeMillis();
//100 millions de déductions(BigDecimal)
for(int i = 0; i < 100_000_000 ; i++){
BigDecimal bigDecimalResultValue = bigDecimalValue1.subtract(bigDecimalValue2);
}
long endBigDecimal = System.currentTimeMillis();
System.out.println("résultat de mesure double: " + (endDouble - startDouble) + "ms");
System.out.println("Résultat de la mesure bigDecimal: " + (endBigDecimal - startBigDecimal) + "ms");
** Résultat d'exécution **
résultat de mesure double: 3ms
Résultat de la mesure bigDecimal: 314ms
Il y avait une différence considérable. Après tout, le type de données de base est rapide!
Eh bien, je me suis personnellement demandé s'il n'y aurait pas de problème avec Big Decimal à moins qu'il y ait beaucoup de boucles ou que des performances soient requises.
Il y a des moments où vous n'avez pas à vous forcer à utiliser des nombres à virgule flottante.
Par exemple, supposons que vous ayez un système qui enregistre votre poids jusqu'au premier chiffre de la fraction. Même s'il est reçu à 65,3 kg en termes d'interface, il peut être traité normalement avec int s'il est décalé de un dans la partie amont du programme et manipulé en interne à 653. Libre de traitement en virgule flottante gênant!
Cependant, cela affecte également la définition de colonne de la base de données, il est donc bon de décider fermement au stade de la conception.
Recommended Posts