1. Introdução
Para emprestar as palavras do livro "Java efativo", os principais objetivos de design de flutuação e tipos duplos são para computação científica e computação em engenharia. Eles realizam operações binárias de ponto flutuante, que são cuidadosamente projetadas para fornecer uma aproximação rápida mais precisa na faixa numérica da área larga. No entanto, eles não fornecem resultados completamente precisos e não devem ser usados em situações em que resultados precisos sejam necessários. No entanto, os cálculos comerciais geralmente requerem resultados precisos, e o BigDecimal é útil no momento.
2. Introdução ao BigDecimal
O BigDecimal consiste em um valor não escala inteiro de qualquer precisão e uma escala inteira de 32 bits. Se for zero ou positivo, a escala é o número de dígitos após o ponto decimal. Se for um número negativo, multiplique o valor não de escala do número por uma potência de escala negativa de 10. Portanto, o valor representado pelo BigDecimal é (não-escaledValue × 10-escala).
3. Código de teste
3.1 Construtor (os principais tipos de parâmetros de teste são dois construtores comuns com dupla e string)
A cópia do código é a seguinte: AddDecimal aduble = new BigDecimal (1.22);
System.out.println ("Construct com um valor duplo:" + AduBle);
Bigdecimal adstring = novo bigdecimal ("1.22");
System.out.println ("Construa com um valor de string:" + adstring);
O que você acha que a saída será? Se você não acha que o primeiro produzirá 1,22, parabéns pela resposta corretamente, o resultado da saída é o seguinte:
Copie o código da seguinte forma: Construa com um DoubleValue: 1.2199999999999999999997335464774089962430298328399658203125
Construa com um valor de string: 1.22
Descrição do JDK:
1. Os resultados do método de construção com o tipo de parâmetro duplo são imprevisíveis. Some people might think that the BigDecimal created by writing newBigDecimal(0.1) in Java is exactly equal to 0.1 (non-scaling value 1, whose scale is 1), but it is actually equal to 0.10000000000000000000000055511151231257827021181583404541015625. Isso ocorre porque 0,1 não pode ser expresso com precisão como um duplo (ou, para este caso, não pode ser expresso como qualquer decimal binário de comprimento finito). Dessa maneira, o valor passado para o método de construção não será exatamente igual a 0,1 (embora seja superficial igual a esse valor).
2. Por outro lado, o método de construção de cordas é completamente previsível: a gravação de NewBigDecimal ("0.1") criará um BigDecimal, o que é exatamente igual ao 0,1 esperado. Portanto, em comparação, geralmente é recomendável usar o construtor de strings primeiro.
3. Quando o duplo deve ser usado como fonte de BigDecimal, observe que este construtor fornece uma conversão precisa; Ele não fornece o mesmo resultado que as seguintes operações: primeiro use o método Double.ToString (Double) e use o construtor BigDecimal (String) para converter o duplo em string. Para obter o resultado, use o método estático (duplo).
3.2 Operação de adição
A cópia do código é a seguinte: bigdecimal a = novo bigdecimal ("1.22");
System.out.println ("Construa com um valor de string:" + a);
Bigdecimal b = novo bigdecimal ("2.22");
A.Add (B);
System.out.println ("Aplus B é:" + a);
É fácil pensar que será lançado:
Copie o código da seguinte forma: Construa com um StringValue: 1.22
a mais B é: 3,44
Mas, de fato, um mais B é: 1,22
4. Análise do código -fonte
4.1 Método ValueOf (DoubleVal)
Copie o código da seguinte
// lembre
// para usar o zero constante. Isso pode ser importante o suficiente para
// justifica uma abordagem de fábrica, um cache ou alguns particulares
// Constantes, mais tarde.
returnnew bigdecimal (duplo.toString (val)); // Veja o terceiro ponto em 3.1 sobre a descrição do JDK
}
4.2 Método ADD (BigDecimal Augend)
public bigdecimal add (bigdecimal augend) {long xs = this.intcompact; // bigdecimal representado por um número inteiro, por exemplo A possui um valor intcompacto de 122 anos longos = augend.intCompact; // o mesmo que acima do biginteger fst = (this.intCompact! = Inflado)? ? null: augend.intval; int rScale = this.cale; // Os decimais lotam sdiff long = (long) rScale - augend.cale; // a diferença entre os lugares decimais se (sdiff! = 0) {// os lugares decimais com os lugares mais decimais são o resultado se (sdiff <0) {ride = ride = checkSDiff); rscale = augend.scale; if (xs == inflado || (xs = longMultiplyPowerten (xs, raise)) == inflado) fst = bigMultiplyPowerten (raise); } else {int raise = augend.checkscale (sdiff); if (ys == inflado || (ys = longMultiplyPowerten (ys, raise)) == inflado) snd = augend.bigmultiplyPowerten (raise); }} if (xs! = inflado && ys! = inflado) {long sum = xs + ys; if ((((soma ^ xs) e (soma ^ ys)))> = 0l) // julgar se há algum estouro. Retornar bigdecimal.valueoOf (soma, rcale); // retorna a instância bigdecimal obtida usando o método de fábrica estática da BigDecimal} if (fst == null) fst = biginteger.valueof (xs); // biginteger de fábrica de fábrica if (snd == nul); Biginteger soma = fst.add (snd); return (fst.signum == snd.signum)? Novo bigdecimal (soma, inflado, rcale, 0): novo bigdecimal (soma, compactValfor (sum), rcale, 0); // retorna o objeto BigDecimal obtido por outros métodos de construção}O exposto acima é apenas uma análise do código -fonte de adição. Subtração, multiplicação e divisão realmente retornam um novo objeto BigDecimal. Como Biginteger e BigDecimal são imutáveis, um novo objeto será gerado ao executar cada etapa da operação, então a.Add (b); Embora a operação de adição seja realizada, A não economiza o valor após a operação de adição. O uso correto deve ser A = A.Add (b);
5. Resumo
(1) Os cálculos comerciais usam BigDecimal.
(2) Tente usar construtores com string de tipo de parâmetro.
(3) BigDecimals são imutáveis. Ao executar cada etapa da operação, um novo objeto será gerado. Portanto, ao executar adição, subtração, multiplicação e divisão, você deve salvar o valor após a operação.
(4) Muitas vezes, tendemos a ignorar alguns detalhes da implementação do JDK subjacente, resultando em erros, por isso precisamos prestar mais atenção.
Referência: classe BigDecimal