Descrição do problema
Ao usar o Java para calcular números de ponto flutuante no projeto, verificou -se que, para cálculos como 4,015*100, o resultado não era o 401.5 esperado, mas 401.499999999999999999999999999999999994. Um número tão longo de dígitos não é amigável para exibição.
Causa do problema: representação do número do ponto flutuante
Após consultar as informações relevantes, descobri que o motivo é que os números de ponto flutuante no computador não podem ser totalmente expressos com precisão. Por exemplo, para um duplo tipo 38414.4, o computador o armazena assim:
Converter em binário: 100101100001110.01100110011001100110011001100110011001100
Transformar em um assunto
Aprenda o método de contagem: 1.0010110000111001100110011001100110011001100110011001100110011001100 × 2^15
O formato de codificação dupla é o seguinte:
Bit de sinal duplo 1 Digit Código de estágio 11 Digit Mantissa 52 dígitos
Bit de símbolo: o número positivo é 0
Código do pedido: 15 é um número positivo, então o bit mais alto é 1, o bit mais baixo é menos 1, que é 10000001110
Mantissue: Remova o padrão 1 do bit mais alto, que é 00101100001110011001100110011001100110011001100110011001100
Combinado, a codificação final é: 0 1000001110 0010110000111001100110011001100110011001100110011001100110011001100
A partir daqui, podemos ver que o principal motivo é que a codificação binária torna a parte fracionária impossível de expressar exatamente exatamente, como 0,4 = 0,25 + 0,125 + ..., que só pode ser infinitamente próximo. Portanto, os erros de precisão ocorrerão ao calcular números de ponto flutuante.
Solução: alta precisão
O BigDecimal em Java pode suportar operações de número de ponto flutuante com precisão arbitrária. No livro "Java eficaz", recomenda -se que flutuação e dupla sejam usados para cálculos científicos ou cálculos de engenharia, enquanto Java.math.bigdecimal é usado em cálculos comerciais.
Existem muitos métodos de construção para BigDecimal, como BigDecimal (Double) e BigDecimal (String). Deve -se notar que os parâmetros de construção são do tipo string para garantir que a precisão não seja perdida, porque o próprio tipo duplo é incompletamente preciso. Portanto, ele precisa ser escrito da seguinte forma: BigDecimal ("0,02").
As operações básicas do tipo duplo podem ser encontradas em BigDecimal. Além disso, o BigDecimal também pode ser usado para formatar a saída com o número -format.
O BigDecimal gerará novos objetos BigDecimal ao fazer operações, por isso trará mais sobrecarga de desempenho em comparação com o dobro.
Um estudo preliminar sobre implementação de alta precisão
Então, como é capaz de representar a precisão arbitrária? Aqui está apenas uma análise preliminar.
Primeiro, vejamos a implementação do Biginteger. O tipo INT comum é de 32 bits, então há uma limitação de intervalo. Biginteger possui a variável de membro Int [] mag, para que a matriz INT mais longa possibilite representar números inteiros de qualquer tamanho.
Vejamos a implementação do BigDecimal. Sua introdução oficial diz que qualquer BigDecimal pode ser representado como não-escala × 10^escala. O UnsCaledValue é um número inteiro de qualquer tamanho, correspondente à variável de membro BigInteger Intval no código -fonte; A escala é a ordem, correspondente à escala INT variável no código -fonte. Dessa forma, o BigDecimal é implementado com base no BigInteger.
O exposto acima é a solução para o problema de precisão do ponto flutuante em Java apresentado a você pelo editor. Espero que seja útil para você. Se você tiver alguma dúvida, deixe -me uma mensagem.