Java BigDecimal: Redondea al valor entero más cercano

90

Necesito los siguientes resultados

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

.round()o .setScale()? ¿Cómo hago con esto?

n / A
fuente

Respuestas:

153

Puede utilizar setScale()para reducir el número de dígitos fraccionarios a cero. Suponiendo que se valuemantiene el valor a redondear:

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

El uso round()es un poco más complicado ya que requiere que especifique el número de dígitos que se conservarán. En sus ejemplos, esto sería 3, pero esto no es válido para todos los valores:

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

(Tenga en cuenta que los BigDecimalobjetos son inmutables; ambos setScaley rounddevolverán un nuevo objeto).

Grodriguez
fuente
1
No funciona: 100.12: 100.12, 100.44: 100.44, 100.50: 100.5, 100.75: 100.75
Boris Pavlović
3
No, la configuración de la escala devuelve un nuevo decimal que no es el mismo que el primero. Por ejemplo: BigDecimal bd1 = new BigDecimal(100.12); BigDecimal bd2 = bd1.setScale(0, RoundingMode.HALF_UP); System.out.println(bd1.equals(bd2));imprime falso
Daniel Fath
6
@Daniel: Eso ya estaba implícito en el fragmento de código que publiqué en mi respuesta. Ahora lo he hecho explícito.
Grodriguez
RoundingMode¿que es eso? EsBigDecimal
trilogía
10

Si sigo la respuesta de Grodriguez

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

Esta es la salida

100.23 -> 100
100.77 -> 101

Lo cual no es exactamente lo que quiero, así que terminé haciendo esto ...

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

Esto es lo que obtengo

100.23 -> 100.00
100.77 -> 101.00

Esto resuelve mi problema por ahora .. :) Gracias a todos.

n / A
fuente
7
Tengo curiosidad por la afirmación de que el primer resultado "no es exactamente lo que quiero ...". Si está realmente preocupado por el formato de salida, puede usar DecimalFormat(como en new DecimalFormat("###.00")) para administrar la conversión de un BigDecimalback to string. Da "101.00"como resultado para ambos valores que los fragmentos de @Grodriquez y usted crearon.
joel.neely
3
La segunda vez que redondeas aquí no es necesario, ya que sabes que ya tienes un número entero, por lo que usaría BigDecimal.ROUND_UNNECESSARY en su lugar, un poco más claro en mi opinión.
kosmoplan
5

Aquí hay una solución terriblemente complicada, pero funciona:

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

Código de prueba:

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());
}

Salida:

100
100
101
101

Sean Patrick Floyd
fuente
No respaldar esta solución ni nada, pero la input.toBigInteger().toString().length()parte sería mucho más eficiente usando un logaritmo, algo comoround_up(log(input)) + (1 if input is a power of ten, else 0)
Addison
0

No creo que puedas redondearlo así con un solo comando. Tratar

    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

Probé el resto de sus ejemplos y devuelve los valores deseados, pero no garantizo que sea correcto.

Daniel Fath
fuente
-2

Usted quiere

round(new MathContext(0));  // or perhaps another math context with rounding mode HALF_UP
jacobm
fuente
2
Esto no hace nada. De la documentación de round: "Si el ajuste de precisión es 0, no se realiza ningún redondeo".
Grodriguez