O princípio igual de BigDecimal em java

BigDecimal, acredito que seja familiar para muitas pessoas, e muitas pessoas conhecem seu uso, que é um tipo fornecido no pacote java.math que pode ser usado para cálculos precisos.

Muitas pessoas sabem que em cenários como representação de valor e cálculo de valor, tipos como double e float não podem ser usados, mas BigDecimal com melhor suporte de precisão deve ser usado.

Portanto, em muitos negócios de pagamento, comércio eletrônico, financeiro e outros, o BigDecimal é usado com muita frequência. E devo dizer que esta é uma classe muito útil, que possui muitos métodos internos, como adição, subtração, multiplicação, divisão e outros métodos de cálculo que podem ser chamados diretamente.

Além da necessidade de usar BigDecimal para representar números e realizar operações digitais, o código muitas vezes precisa julgar a igualdade dos números.

Com relação a esse ponto de conhecimento, também é explicado na versão mais recente do "Manual de desenvolvimento do Alibaba Java":

![][1]

Qual é o pensamento por trás disso?

Eu vi erros de baixo nível como os seguintes em CodeReviews anteriores:

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

Esse tipo de erro, acredito que os leitores inteligentes podem ver o problema de relance, porque BigDecimal é um objeto, portanto não pode ser ==usado para julgar se os valores de dois números são iguais.

Os problemas acima ainda podem ser evitados depois de ter alguma experiência, mas leitores espertos, dê uma olhada na seguinte linha de código, você acha que há algum problema com isso:

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

Posso dizer claramente que o método de escrita acima pode resultar em resultados diferentes do que você esperava!

Vamos fazer um experimento primeiro, execute o seguinte 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));

O código acima, o resultado de saída é:

true
true
false

Princípio da igualdade de BigDecimal

Através do exemplo de código acima, descobrimos que ao usar o método equals de BigDecimal para comparar 1 e 1.0, às vezes é verdadeiro (ao usar int, double para definir BigDecimal), às vezes é falso (ao usar String para definir BigDecimal hora) .

Então, por que isso acontece?Vamos primeiro olhar para o método equals de BigDecimal.

O motivo é realmente explicado no JavaDoc do 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)

Provavelmente significa que o método equals não é o mesmo que compareTo. O método equals irá comparar duas partes, ou seja, o valor (valor) e a escala (escala)

O código correspondente é o seguinte:

![][2]

Portanto, as escalas dos dois objetos BigDecimal (bigDecimal4 e bigDecimal5) definidas pelo nosso código acima são diferentes, então o resultado de usar equals para comparar é falso.

Tente depurar o código. Durante o processo de depuração, também podemos ver que a escala de bigDecimal4 é 0, enquanto a escala de bigDecimal5 é 1.

![][3]

Neste ponto, provavelmente explicamos claramente que a razão pela qual o resultado de equals comparando bigDecimal4 e bigDecimal5 é falso é porque as escalas são diferentes.

Então, por que as escalas são diferentes? Por que as escalas de bigDecimal2 e bigDecimal3 são as mesmas (ao usar int e double para definir BigDecimal), mas bigDecimal4 e bigDecimal5 não são as mesmas (ao usar String para definir BigDecimal)?

porque a escala é diferente

Isso envolve o problema de escala do BigDecimal.Na verdade esse problema é mais complicado.Como não é o foco deste artigo, vamos apresentá-lo brevemente aqui. Se você estiver interessado, falarei sobre isso separadamente mais tarde.

Em primeiro lugar, BigDecimal tem os seguintes quatro métodos de construção:

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

As escalas do BigDecimal criadas pelos quatro métodos acima são diferentes.

BigDecimal(long) e BigDecimal(int)

Primeiramente, os mais simples são BigDecimal(long) e BigDecimal(int), por serem números inteiros, a escala é 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(duplo)

Para BigDecimal(double), quando usamos new BigDecimal(0.1) para criar um BigDecimal, o valor criado não é exatamente igual a 0.1, mas 0.1000000000000000055511151231257827021181583404541015625. Isso ocorre porque a própria doule representa apenas uma aproximação.

Então, se usarmos new BigDecimal(0.1) ou new BigDecimal(0.10) para definir, seu valor aproximado é 0,1000000000000000055511151231257827021181583404541015625, então sua escala é o número de dígitos desse número, que é 55.

![][4]

O mesmo vale para outros números de ponto flutuante. Para um formulário como new BigDecimal(1.0), já que ele é essencialmente um número inteiro, a escala do número que ele cria é 0.

Portanto, como as escalas de BigDecimal(1.0) e BigDecimal(1.00) são iguais, ao usar o método equals para comparar, o resultado é verdadeiro.

BigDecimal(string)

Para BigDecimal(double), quando usamos new BigDecimal("0.1") para criar um BigDecimal, o valor criado é exatamente igual a 0.1. Então sua escala é 1.

Se você usar new BigDecimal("0.10000"), o número criado será 0,10000 e a escala será 5.

Portanto, como as escalas de BigDecimal("1.0") e BigDecimal("1.00") são diferentes, ao usar o método equals para comparar, o resultado é falso.

Como comparar BigDecimal

Anteriormente, explicamos o método equals de BigDecimal, que não apenas compara o valor dos números, mas também compara suas escalas.

Portanto, quando usamos o método equals para julgar se dois números são iguais, ele é extremamente rigoroso.

Então, se quisermos apenas julgar se os valores de dois BigDecimal são iguais, como devemos julgar?

O método compareTo é fornecido no BigDecimal, que só pode comparar os valores de dois números, e retornar 0 se os dois números forem iguais.

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

O código acima, o resultado de saída:

0

Seu código fonte é o seguinte:

![][5]

Resumir

BigDecimal é uma classe muito útil para representar números de alta precisão, que fornece muitos métodos avançados.

No entanto, ele precisa ser cauteloso ao usar o método equals, pois quando ele compara, ele não compara apenas os valores de dois números, mas também compara suas escalas. Desde que um desses dois fatores não seja igual, o resultado também é falso,

Se os leitores quiserem comparar dois valores BigDecimal, eles podem usar o método compareTo.

Acho que você gosta

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