ArithmeticException: “Espansione decimale non terminante; nessun risultato decimale rappresentabile esatto ”


507

Perché il seguente codice solleva l'eccezione mostrata di seguito?

BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.

Eccezione:

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

Risposte:


843

Dai documenti Java 11BigDecimal :

Quando un MathContextoggetto viene fornito con un'impostazione di precisione pari a 0 (ad esempio, MathContext.UNLIMITED), le operazioni aritmetiche sono esatte, così come i metodi aritmetici che non accettano alcun MathContextoggetto. (Questo è l'unico comportamento supportato nelle versioni precedenti alla 5.)

Come corollario del calcolo del risultato esatto, l'impostazione della modalità di arrotondamento di un MathContextoggetto con un'impostazione di precisione pari a 0 non viene utilizzata e quindi irrilevante. In caso di divisione, il quoziente esatto potrebbe avere un'espansione decimale infinitamente lunga; ad esempio, 1 diviso per 3.

Se il quoziente ha un'espansione decimale non terminante e l'operazione viene specificata per restituire un risultato esatto, ArithmeticExceptionviene generata una. Altrimenti, viene restituito il risultato esatto della divisione, come fatto per altre operazioni.

Per risolvere, devi fare qualcosa del genere :

a.divide(b, 2, RoundingMode.HALF_UP)

dove 2 è la scala e RoundingMode.HALF_UP è la modalità di arrotondamento

Per maggiori dettagli vedi questo post sul blog .


3
questo funziona anche per errore di diaspro grazie community.jaspersoft.com/questions/528968/…
shareef

27
2 NON è precision; lo è scale. Si prega di consultare docs.oracle.com/javase/7/docs/api/java/math/…
John Manko,

(nuovo BigDecimal (100)). divide (nuovo BigDecimal (0.90), 2,
RoundingMode.HALF_UP

@AnandVarkeyPhilips È la scala. Vedi il Javadoc . Modifica rifiutata.
Marchese di Lorne

@ user207421, l'ho modificato accidentalmente e ho provato a ripristinare .. Ma non avevo abbastanza punti per eliminare una modifica .... meta.stackexchange.com/questions/80933/…
Anand Varkey Philips

76

Perché non stai specificando una precisione e una modalità di arrotondamento. BigDecimal si lamenta del fatto che potrebbe usare 10, 20, 5000 o infiniti decimali e non sarebbe ancora in grado di darti una rappresentazione esatta del numero. Quindi, invece di darti un BigDecimal errato, ti piagnucola e basta.

Tuttavia, se fornisci un RoundingMode e una precisione, allora sarà in grado di convertire (es. 1.333333333-in-infinito in qualcosa come 1.3333 ... ma tu come programmatore devi dirgli con quale precisione sei 'soddisfatto '.



13

Per risolvere un problema del genere ho usato il codice seguente

a.divide(b, 2, RoundingMode.HALF_EVEN)

2 è precisione. Ora il problema è stato risolto.


3
oltre al codice, dovrebbero essere fornite alcune spiegazioni.
Martin Serrano,

11
2 NON è precision; lo è scale. Si prega di consultare docs.oracle.com/javase/7/docs/api/java/math/…
John Manko,

3
RoundingMode.HALF_EVEN è raccomandato per applicazioni finanziarie. Questo è ciò che viene utilizzato nel settore bancario
ACV

Per coloro che sono confusi dal commento di John Mankos sulla precisione, vedere questa risposta stackoverflow.com/questions/4591206/…
Stimpson Cat,

5

Ho avuto lo stesso problema, perché la mia riga di codice era:

txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");

Passo a questo, leggendo la risposta precedente, perché non stavo scrivendo una precisione decimale:

txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");

4 è Decimal Precison

E RoundingMode sono costanti di Enum, puoi scegliere una qualsiasi di queste UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

In questo caso HALF_UP avrà questo risultato:

2.4 = 2   
2.5 = 3   
2.7 = 3

Puoi controllare le RoundingModeinformazioni qui: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/


4 è la scala, non la precisione.
Marchese di Lorne

3

Si tratta di arrotondare il risultato, la soluzione per me è la seguente.

divider.divide(dividend,RoundingMode.HALF_UP);

1

Risposta per BigDecimal genera ArithmeticException

public static void main(String[] args) {
        int age = 30;
        BigDecimal retireMentFund = new BigDecimal("10000.00");
        retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
        BigDecimal yearsInRetirement = new BigDecimal("20.00");
        String name = " Dennis";
        for ( int i = age; i <=65; i++){
            recalculate(retireMentFund,new BigDecimal("0.10"));
        }
        BigDecimal monthlyPension =   retireMentFund.divide(
                yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));      
        System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
    }
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
        fundAmount.multiply(rate.add(new BigDecimal("1.00")));
    }

Aggiungi l'oggetto MathContext nella chiamata del metodo di divisione e regola la modalità di precisione e arrotondamento. Questo dovrebbe risolvere il tuo problema


0

Il tuo programma non sa quale precisione utilizzare per i numeri decimali, quindi genera:

java.lang.ArithmeticException: Non-terminating decimal expansion

Soluzione per bypassare l'eccezione:

MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.