Java BigDecimal: arrotondare al valore intero più vicino


89

Ho bisogno dei seguenti risultati

100.12 -> 100.00
100.44 -> 100.00
100.50 -> 101.00
100.75 -> 101.00

.round()o .setScale()? Come posso procedere?

Risposte:


151

È possibile utilizzare setScale()per ridurre il numero di cifre frazionarie a zero. Supponendo che valuecontenga il valore da arrotondare:

BigDecimal scaled = value.setScale(0, RoundingMode.HALF_UP);
System.out.println(value + " -> " + scaled);

L'utilizzo round()è un po 'più complicato in quanto richiede di specificare il numero di cifre da conservare. Nei tuoi esempi questo sarebbe 3, ma non è valido per tutti i valori:

BigDecimal rounded = value.round(new MathContext(3, RoundingMode.HALF_UP));
System.out.println(value + " -> " + rounded);

(Nota che gli BigDecimaloggetti sono immutabili; entrambi setScalee roundrestituiranno un nuovo oggetto.)


1
Non funziona: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75
— Boris Pavlović

3
No, l'impostazione della scala restituisce un nuovo decimale diverso dal primo. Ad esempio: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));stampe false
— Daniel Fath

6
@ Daniel: Questo era già implicito nello snippet di codice che ho pubblicato nella mia risposta. Ora l'ho reso esplicito.
— Grodriguez

RoundingModeCos'è quello? ÈBigDecimal
— trilogia


10

Se vado dalla risposta di Grodriguez

System.out.println("" + value);
value = value.setScale(0, BigDecimal.ROUND_HALF_UP);
System.out.println("" + value);

Questo è l'output

100.23 -> 100
100.77 -> 101

Che non è proprio quello che voglio, quindi ho finito per farlo ..

System.out.println("" + value);
value = value.setScale(0, BigDecimal.ROUND_HALF_UP);
value = value.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("" + value);

Questo è quello che ottengo

100.23 -> 100.00
100.77 -> 101.00

Questo risolve il mio problema per ora ..:) Grazie a tutti.


7
Mi incuriosisce l'affermazione che il primo risultato "non è proprio quello che voglio ...". Se sei effettivamente preoccupato per la formattazione dell'output, puoi usare DecimalFormat(come in new DecimalFormat("###.00")) per gestire la conversione di un BigDecimalback to string. Fornisce "101.00"come risultato entrambi i valori che gli snippet di @Grodriquez e tu hai creato.
— joel.neely

3
La seconda volta che esegui l'arrotondamento qui non è necessaria perché sai che hai già un numero intero, quindi userei BigDecimal.ROUND_UNNECESSARY invece, un po 'più chiaro secondo me.
— kosmoplan

5

Ecco una soluzione terribilmente complicata, ma funziona:

public static BigDecimal roundBigDecimal(final BigDecimal input){
    return input.round(
        new MathContext(
            input.toBigInteger().toString().length(),
            RoundingMode.HALF_UP
        )
    );
}

Codice di prova:

List<BigDecimal> bigDecimals =
    Arrays.asList(new BigDecimal("100.12"),
        new BigDecimal("100.44"),
        new BigDecimal("100.50"),
        new BigDecimal("100.75"));
for(final BigDecimal bd : bigDecimals){
    System.out.println(roundBigDecimal(bd).toPlainString());
}

Produzione:

100
100
101
101


Non per approvare questa soluzione o altro, ma la input.toBigInteger().toString().length()parte sarebbe molto più efficiente utilizzando un logaritmo, qualcosa comeround_up(log(input)) + (1 if input is a power of ten, else 0)
— Addison,


0

Non credo che tu possa arrotondarlo in quel modo con un singolo comando. Provare

    ArrayList<BigDecimal> list = new ArrayList<BigDecimal>();
    list.add(new BigDecimal("100.12"));
    list.add(new BigDecimal("100.44"));
    list.add(new BigDecimal("100.50"));
    list.add(new BigDecimal("100.75"));

    for (BigDecimal bd : list){
        System.out.println(bd+" -> "+bd.setScale(0,RoundingMode.HALF_UP).setScale(2));
    }

Output:
100.12 -> 100.00
100.44 -> 100.00
100.50 -> 101.00
100.75 -> 101.00

Ho testato il resto dei tuoi esempi e restituisce i valori desiderati, ma non garantisco la sua correttezza.


-2

Tu vuoi

round(new MathContext(0));  // or perhaps another math context with rounding mode HALF_UP

2
Questo non fa niente. Dalla documentazione di round: "Se l'impostazione della precisione è 0, non viene eseguito alcun arrotondamento."
— Grodriguez
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.