BigDecimal: HALF_UP redondeo con setScale

Orkin Ozen:

Tenemos el siguiente código:

BigDecimal net = price
.divide(taxCumulative, RoundingMode.HALF_UP)
.setScale(2, BigDecimal.ROUND_UP); 

Estamos unidad de prueba de esto y conseguir resultados diferentes dependiendo de si se utiliza @Transactionalen las clases de prueba o no.

Sólo quiero saber si debemos esperar que la aplicación de la HALF_UPque se considera junto con el setScaleo antes de ella.

Por ejemplo:

Dilo :

precio = 4,00

taxCumulative = 1,20

¿Es de esperar que el cálculo sea como:

un) 4.00 / 1.20 = 3.33333333... --> HALF_UP --> 3 --> setScale --> 3

o

si) 4.00 / 1.20 = 3.33333333... --> HALF_UP with setScale 2 --> 3.33

Como dije, tenemos pruebas de unidad en contra de este código que se comporta de forma diferente cuando tenemos el @Transactionalo no. Así que no pudimos concluir. En el mundo real, el resultado es b . Pero una también tiene sentido.

¿Alguna idea?

ACTUALIZACIÓN :

Tras @ sugerencias de Mark, me he creado una prueba fuera del contexto de la primavera. (Pero supongo que no hay manera de compartir en línea como codepen).

package com.company;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {

    public static void main(String[] args) {
        BigDecimal price = new BigDecimal("4.00");
        BigDecimal taxCumulative = new BigDecimal("1.20");
        BigDecimal net = price.divide(taxCumulative, RoundingMode.HALF_UP).setScale(2, BigDecimal.ROUND_UP);
        System.out.println("With String constructor, the net =  " + net.toString());
        // prints 3.33
        price = new BigDecimal(4.00);
        taxCumulative = new BigDecimal(1.20);
        net = price.divide(taxCumulative, RoundingMode.HALF_UP).setScale(2, BigDecimal.ROUND_UP);
        System.out.println("With doubles, the net =  " + net.toString());
        // prints 3.00
    }
}

Así que, como salir en punta por @gtgaxiola el constructor de cadena que hace la diferencia.

Y en cuanto a la cuestión de la utilización de setScale para la operación de división. He hecho algunas pruebas más:

price = new BigDecimal("4.000000");
taxCumulative = new BigDecimal("1.2000000");
net = price.divide(taxCumulative, RoundingMode.HALF_UP).setScale(2, BigDecimal.ROUND_UP);
// 3.34

price = new BigDecimal("4.000000");
taxCumulative = new BigDecimal("1.2000000");
net = price.divide(taxCumulative, RoundingMode.HALF_UP);
// 3.333333

price = new BigDecimal("4");
taxCumulative = new BigDecimal("1.2");
net = price.divide(taxCumulative, RoundingMode.HALF_UP);
// 3

Así, el resultado depende en gran medida de la precisión de la entrada de cadena y se aplica el setScale después de la brecha da su resultado.

gtgaxiola:

Parecería que se ve afectado dependiendo de cómo se construye su BigDecimal

Consulte las notas de constructor de BigDecimal pública (doble val)

1.- Los resultados de este constructor puede ser algo impredecible. Se podría suponer que la escritura new BigDecimal (0,1) en Java crea un BigDecimal que es exactamente igual a 0,1 (un valor sin escala de 1, con una escala de 1), pero en realidad es igual a 0,1000000000000000055511151231257827021181583404541015625. Esto se debe a 0.1 no se puede representar exactamente como una doble (o, para el caso, como una fracción binaria de cualquier longitud finita). Por lo tanto, el valor que se pasa en al constructor no es exactamente igual a 0,1, las apariencias no obstante.

2.-El constructor de String, por otro lado, es perfectamente previsible: escribir nuevo BigDecimal ( "0.1") crea un BigDecimal que es exactamente igual a 0,1, como era de esperar. Por lo tanto, se recomienda generalmente que el constructor de String ser utilizado con preferencia a éste.

3.-Cuando un doble debe ser utilizado como una fuente para un BigDecimal, nota que este constructor proporciona una conversión exacta; no da el mismo resultado que la conversión de la doble en una cadena utilizando el método Double.toString (doble) y a continuación, utilizando el constructor BigDecimal (String). Para obtener ese resultado, utilice el método valueOf (doble) estática.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=189586&siteId=1
Recomendado
Clasificación