java double précision, plutôt BigDecimal et MathContext
Par PlaceOweb le lundi, octobre 13 2014, 23:33 - JAVA - Lien permanent
La précision du double peut générer des nombres extravagants... généralement cela conduit à l'utilisation de la classe BigDecimal...
public static void main(String[] args) {
System.out.println("13.8 + 85.8 + 4.6 = 104.2 ?...");
System.out.println("-- Avec (D/d)ouble");
double doubleTotal = 0;
double doubleArray[] = {13.8, 85.8, 4.6};
for (int i = 0; i < doubleArray.length; i++) {
doubleTotal += doubleArray[i];
System.out.println(doubleTotal);
}
System.out.println("-- Avec BigDecimal");
BigDecimal bigDecimalTotal = new BigDecimal(0);
BigDecimal bigDecimalArray[] = {new BigDecimal(13.8), new BigDecimal(85.8), new BigDecimal(4.6)};
for (int i = 0; i < bigDecimalArray.length; i++) {
// bigDecimalTotal += bigDecimalArray[i]; // The operator += is undefined for the argument type(s) java.math.BigDecimal, java.math.BigDecimal
bigDecimalTotal = bigDecimalTotal.add(bigDecimalArray[i]);
System.out.println(bigDecimalTotal);
}
System.out.println("-- Avec BigDecimal - from parse string");
BigDecimal bigDecimalStringTotal = new BigDecimal(0);
BigDecimal bigDecimalStringArray[] = {new BigDecimal("13.8"), new BigDecimal("85.8"), new BigDecimal("4.6")};
for (int i = 0; i < bigDecimalStringArray.length; i++) {
bigDecimalStringTotal = bigDecimalStringTotal.add(bigDecimalStringArray[i]);
System.out.println(bigDecimalStringTotal);
}
// http://piotrnowicki.com/2011/02/precision-and-scale-in-bigdecimal-and-mathcontext/
// You should use new BigDecimal(String) in the first place.
// If you need to use double, then new BigDecimal.valueOf(double) or equivalent new BigDecimal(Double.toString(double)) should behave more expectably
MathContext mc = new MathContext(4);
System.out.println("-- Avec BigDecimal + MathContext(4)");
BigDecimal bigDecimalMcTotal = new BigDecimal(0);
BigDecimal bigDecimalMcArray[] = {new BigDecimal(13.8), new BigDecimal(85.8), new BigDecimal(4.6)};
for (int i = 0; i < bigDecimalMcArray.length; i++) {
bigDecimalMcTotal = bigDecimalMcTotal.add(bigDecimalMcArray[i], mc);
System.out.println(bigDecimalMcTotal.toPlainString());
}
System.exit(0);
// 13.8 + 85.8 + 4.6 = 104.2 ?...
// -- Avec (D/d)ouble
// 13.8
// 99.6
// 104.19999999999999
// -- Avec BigDecimal
// 13.800000000000000710542735760100185871124267578125
// 99.599999999999997868371792719699442386627197265625
// 104.1999999999999975131004248396493494510650634765625
// -- Avec BigDecimal - from parse string
// 13.8
// 99.6
// 104.2
// -- Avec BigDecimal + MathContext(4)
// 13.80
// 99.60
// 104.2
Ressources
- Precision and scale in BigDecimal and MathContext
- new BigDecimal(double); is not a very good idea to begin with. You should use new BigDecimal(String) in the first place. If you need to use double, then new BigDecimal.valueOf(double) or equivalent new BigDecimal(Double.toString(double)) should behave more expectably.
- Use of java.math.MathContext
- java.math
- BigDecimal - MathContext.DECIMAL64 vs MathContext.DECIMAL128
- Decimal types - Decimal 32/64/128 datatype
Exemple de résultat de division avec un MathContext.DECIMAL défini.
166.4310 // MathContext.DECIMAL32 3+ 4 décimales au total 7 digit 166.4310382495999 // MathContext.DECIMAL64 3+13 décimales au total 16 digits 166.4310382495999118394932666158574 // MathContext.DECIMAL128 3+31 décimales au total 34 digits
Si on ne définit pas le MathContexte, avec cette division au résultat infini, on prend une : java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.