El principio de igualdad de BigDecimal en Java

BigDecimal, creo que es familiar para muchas personas, y muchas personas conocen su uso, que es un tipo provisto en el paquete java.math que se puede usar para cálculos precisos.

Mucha gente sabe que en escenarios como la representación de montos y el cálculo de montos, no se pueden usar tipos como double y float, pero se debe usar BigDecimal con un mejor soporte de precisión.

Por lo tanto, en muchos pagos, comercio electrónico, negocios financieros y otros, BigDecimal se usa con mucha frecuencia. Y debo decir que esta es una clase muy útil, que tiene muchos métodos dentro, como suma, resta, multiplicación, división y otros métodos de cálculo que se pueden llamar directamente.

Además de la necesidad de usar BigDecimal para representar números y realizar operaciones digitales, el código a menudo necesita juzgar la igualdad de los números.

Con respecto a este punto de conocimiento, también se explica en la última versión del "Manual de desarrollo de Java de Alibaba":

![][1]

¿Cuál es el pensamiento detrás de esto?

He visto errores de bajo nivel como los siguientes en CodeReviews anteriores:

if(bigDecimal == bigDecimal1){
    // 两个数相等
}

Este tipo de error, creo que los lectores inteligentes pueden ver el problema de un vistazo, porque BigDecimal es un objeto, por lo que no se puede ==usar para juzgar si los valores de dos números son iguales.

Los problemas anteriores aún se pueden evitar después de tener algo de experiencia, pero lectores inteligentes, echen un vistazo a la siguiente línea de código, ¿creen que hay algún problema con ella?

if(bigDecimal.equals(bigDecimal1)){
    // 两个数相等
}

¡Puedo decirle claramente que el método de escritura anterior puede generar resultados diferentes a los que esperaba!

Primero hagamos un experimento, ejecute el siguiente código:

BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));

BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));

BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));

El código anterior, el resultado de salida es:

true
true
false

Principio de igualdad de BigDecimal

A través del ejemplo de código anterior, encontramos que cuando usamos el método de igualdad de BigDecimal para comparar 1 y 1.0, a veces es verdadero (cuando usamos int, double para definir BigDecimal), a veces es falso (cuando usamos String para definir BigDecimal hora) .

Entonces, ¿por qué sucede esto? Veamos primero el método equals de BigDecimal.

La razón en realidad se explica en JavaDoc de BigDecimal:

Compares this  BigDecimal with the specified Object for equality.  Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by  this method)

Probablemente significa que el método equals no es lo mismo que compareTo. El método equals comparará dos partes, a saber, el valor (valor) y la escala (escala)

El código correspondiente es el siguiente:

![][2]

Por lo tanto, las escalas de los dos objetos BigDecimal (bigDecimal4 y bigDecimal5) definidas por nuestro código anterior son diferentes, por lo que el resultado de usar iguales para comparar es falso.

Intenta depurar el código Durante el proceso de depuración, también podemos ver que la escala de bigDecimal4 es 0, mientras que la escala de bigDecimal5 es 1.

![][3]

En este punto, probablemente explicamos claramente que la razón por la cual el resultado de igual a comparar bigDecimal4 y bigDecimal5 es falso es porque las escalas son diferentes.

Entonces, ¿por qué las escalas son diferentes? ¿Por qué las escalas de bigDecimal2 y bigDecimal3 son iguales (cuando se usa int y double para definir BigDecimal), pero bigDecimal4 y bigDecimal5 no son iguales (cuando se usa String para definir BigDecimal)?

por qué la escala es diferente

Esto implica el problema de escalado de BigDecimal. Este problema es en realidad más complicado. Dado que no es el enfoque de este artículo, vamos a presentarlo brevemente aquí. Si está interesado, hablaré de eso por separado más adelante.

En primer lugar, BigDecimal tiene los siguientes cuatro métodos de construcción:

BigDecimal(int)
BigDecimal(double) 
BigDecimal(long) 
BigDecimal(String)

Las escalas del BigDecimal creado por los cuatro métodos anteriores son diferentes.

BigDecimal(largo) 和BigDecimal(int)

En primer lugar, los más simples son BigDecimal(long) y BigDecimal(int), porque son números enteros, la escala es 0 :

public BigDecimal(int val) {
    this.intCompact = val;
    this.scale = 0;
    this.intVal = null;
}

public BigDecimal(long val) {
    this.intCompact = val;
    this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
    this.scale = 0;
}

BigDecimal(doble)

Para BigDecimal(doble), cuando usamos new BigDecimal(0.1) para crear un BigDecimal, el valor creado no es exactamente igual a 0.1, sino 0.1000000000000000055511151231257827021181583404541015625. Esto se debe a que la doule en sí representa solo una aproximación.

Entonces, si usamos new BigDecimal(0.1) o new BigDecimal(0.10) para definir, su valor aproximado es 0.1000000000000000055511151231257827021181583404541015625, entonces su escala es el número de dígitos de este número, que es 55.

![][4]

Lo mismo es cierto para otros números de coma flotante. Para una forma como new BigDecimal(1.0), dado que es esencialmente un número entero, la escala del número que crea es 0.

Por lo tanto, debido a que las escalas de BigDecimal(1.0) y BigDecimal(1.00) son iguales, cuando se usa el método de igualdad para comparar, el resultado es verdadero.

BigDecimal(cadena)

Para BigDecimal(doble), cuando usamos new BigDecimal("0.1") para crear un BigDecimal, el valor creado es exactamente igual a 0.1. Entonces su escala es 1.

Si usa el nuevo BigDecimal ("0.10000"), entonces el número creado es 0.10000 y la escala es 5.

Por lo tanto, debido a que las escalas de BigDecimal("1.0") y BigDecimal("1.00") son diferentes, cuando se usa el método de igualdad para comparar, el resultado es falso.

Cómo comparar BigDecimal

Anteriormente, explicamos el método de igualdad de BigDecimal, que no solo compara el valor de los números, sino que también compara sus escalas.

Por lo tanto, cuando usamos el método de igualdad para juzgar si dos números son iguales, es extremadamente estricto.

Entonces, si solo queremos juzgar si los valores de dos BigDecimal son iguales, ¿cómo debemos juzgar?

El método compareTo se proporciona en BigDecimal, que solo puede comparar los valores de dos números y devolver 0 si los dos números son iguales.

    BigDecimal bigDecimal4 = new BigDecimal("1");
    BigDecimal bigDecimal5 = new BigDecimal("1.0000");
    System.out.println(bigDecimal4.compareTo(bigDecimal5));

El código anterior, el resultado de salida:

0

Su código fuente es el siguiente:

![][5]

Resumir

BigDecimal es una clase muy útil para representar números de alta precisión, que proporciona muchos métodos enriquecidos.

Sin embargo, debe tener cuidado al usar el método de igualdad, porque cuando compara, no solo compara los valores de dos números, sino que también compara sus escalas, siempre que uno de estos dos factores no sea igual, el resultado tambien es falso,

Si los lectores quieren comparar dos valores BigDecimal, pueden usar el método compareTo.

Supongo que te gusta

Origin blog.csdn.net/zy_dreamer/article/details/132350257
Recomendado
Clasificación