Domanda

Recentemente ho provato a capire l'uso di java.math.MathContext ma non sono riuscito a capire bene.Viene utilizzato per arrotondare? java.math.BigDecimal.Se sì, perché non arrotonda le cifre decimali ma nemmeno la parte della mantissa.

Dai documenti API, sono venuto a sapere che segue lo standard specificato in ANSI X3.274-1996 E ANSI X3.274-1996/AM 1-2000 specifiche ma non le ho fatte leggere online.

Per favore fatemi sapere se avete qualche idea al riguardo.

È stato utile?

Soluzione

@jatan

Grazie per la risposta.Ha senso.Puoi per favore spiegarmi MathContext nel contesto del metodo BigDecimal#round.

Non c'è niente di speciale BigDecimal.round() contro qualsiasi altro BigDecimal metodo.In tutti i casi, il MathContext specifica il numero di cifre significative e la tecnica di arrotondamento.Fondamentalmente, ci sono due parti di ciascuno MathContext.C'è una precisione e c'è anche una RoundingMode.

La precisione specifica nuovamente il numero di cifre significative.Quindi se specifichi 123 come numero e chiedi 2 cifre significative, otterrai 120.Potrebbe essere più chiaro se pensi in termini di notazione scientifica.

123 sarebbe 1.23e2 nella notazione scientifica.Se mantieni solo 2 cifre significative, ottieni 1.2e2, O 120.Riducendo il numero di cifre significative, riduciamo la precisione con cui possiamo specificare un numero.

IL RoundingMode la parte specifica come dovremmo gestire la perdita di precisione.Per riutilizzare l'esempio, se usi 123 come numero e chiedi 2 cifre significative, hai ridotto la precisione.Con un RoundingMode Di HALF_UP (la modalità predefinita), 123 diventerà 120.Con un RoundingMode Di CEILING, otterrai 130.

Per esempio:

System.out.println(new BigDecimal("123.4",
                   new MathContext(4,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(2,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(2,RoundingMode.CEILING)));
System.out.println(new BigDecimal("123.4",
                   new MathContext(1,RoundingMode.CEILING)));

Uscite:

123.4
1.2E+2
1.3E+2
2E+2

Puoi vedere che sia la precisione che la modalità di arrotondamento influiscono sull'output.

Altri suggerimenti

Per arrotondare solo la parte frazionaria di un BigDecimal, consulta il file BigDecimal.setScale(int newScale, int roundingMode) metodo.

Per esempio.per modificare un numero con tre cifre dopo la virgola in uno con due cifre e arrotondando per eccesso:

BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);

Il risultato è un BigDecimal con il valore 1.24 (a causa della regola di arrotondamento)

Vorrei aggiungere qui alcuni esempi.Non li ho trovati nelle risposte precedenti, ma li trovo utili per chi magari trarre in inganno cifre significative con numero di decimali.Supponiamo di avere tale contesto:

MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);

Per questo codice:

BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);

è perfettamente chiaro che il tuo risultato è 1.23E+3 come hanno detto i ragazzi sopra.Le prime cifre significative sono 123...

Ma cosa succede in questo caso:

BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX);
System.out.println(d2);

il tuo numero non verrà arrotondato a 3 cifre dopo la virgola - per qualcuno può non essere intuitivo e vale la pena sottolinearlo.Verrà invece arrotondato a prime 3 cifre significative, che in questo caso sono "4 5 4".Quindi il codice sopra risulta 4.55E-7 e non dentro 0.000 come qualcuno potrebbe aspettarsi.

Esempi simili:

BigDecimal d3 = new BigDecimal(0.001000045477, MATH_CTX);
 System.out.println(d3);  // 0.00100

BigDecimal d4 = new BigDecimal(0.200000477, MATH_CTX);
 System.out.println(d4);   // 0.200

BigDecimal d5 = new BigDecimal(0.000000004, MATH_CTX);
    System.out.println(d5); //4.00E-9

Spero che questo esempio ovvio ma pertinente possa essere utile...

Se ho capito bene, sembra che ti aspetti che MathContext controlli quante cifre devono essere mantenute dopo il punto decimale.Non è a questo che serve.Specifica quante cifre mantenere, totale.Quindi se specifichi che vuoi 3 cifre significative, è tutto ciò che otterrai.

Ad esempio, questo:

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(20)));

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(10)));

System.out.println(new BigDecimal("1234567890.123456789",
                   new MathContext(5)));

restituirà:

1234567890.123456789
1234567890
1.2346E+9

Non è per divertimento.In realtà ho trovato qualche esempio online, che dichiarava l'uso di MathContext per arrotondare gli importi/numeri memorizzati in BigDecimal.

Per esempio,

Se MathContext è configurato per avere precision = 2 E rounding mode = ROUND_HALF_EVEN

BigDecimal Number = 0.5294, È arrotondato A 0.53

Quindi ho pensato che fosse una tecnica più nuova e l'ho usata per arrotondare.Tuttavia si è trasformato in un incubo perché ha iniziato ad arrotondare anche una parte mentissa del numero.

Per esempio,

Number = 1.5294 è arrotondato a 1.5

Number = 10.5294 è arrotondato a 10

Number = 101.5294 è arrotondato a 100

....e così via

Quindi questo non è il comportamento che mi aspettavo per l'arrotondamento (poiché precisione = 2).

Sembra avere una logica perché da patter posso dire che ci vogliono le prime due cifre (poiché la precisione è 2) del numero e poi aggiunge 0 fino al no.di cifre diventano uguali all'importo non arrotondato (controlla l'esempio di 101.5294 ...)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top