O que eu gostaria é de um método para converter um duplo em uma string que arredonde usando o método half-up - ou seja, se o decimal a ser arredondado for 5, ele sempre arredondará para o próximo número. Esse é o método padrão de arredondamento que a maioria das pessoas espera na maioria das situações.
Eu também gostaria que apenas dígitos significativos fossem exibidos - ou seja, não deveria haver zeros à direita.
Eu sei que um método para fazer isso é usar o String.format
método:
String.format("%.5g%n", 0.912385);
retorna:
0.91239
o que é ótimo, porém sempre exibe números com 5 casas decimais, mesmo que não sejam significativos:
String.format("%.5g%n", 0.912300);
retorna:
0.91230
Outro método é usar o DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
retorna:
0.91238
No entanto, como você pode ver, isso usa arredondamentos semi-uniformes. Ou seja, será arredondado para baixo se o dígito anterior for par. O que eu gostaria é isso:
0.912385 -> 0.91239
0.912300 -> 0.9123
Qual é a melhor maneira de conseguir isso em Java?
"#.##"
:, arredondamentoHALF_UP
.256.335f
->"256.33"
... (exemplo vem de comentários para a resposta de @ asterita).Assumindo que
value
é umdouble
, você pode fazer:Isso é para precisão de 5 dígitos. O número de zeros indica o número de casas decimais.
fonte
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.265.335
realmente significa265.335 += tolerance
, onde a tolerância depende de operações anteriores e da faixa de valores de entrada. Não sabemos o valor exato e verdadeiro. Nos valores de borda, qualquer uma das respostas está indiscutivelmente correta. Se precisarmos ser exatos, não devemos trabalhar em dobro. Ofail
aqui não está na conversão de volta para o dobro. Está pensando em OP, que ele pode confiar na entrada265.335
como exatamente isso.você receberá um
BigDecimal
. Para obter a cadeia de fora, é só chamar queBigDecimal
'stoString
método ou otoPlainString
método de Java 5+ para uma seqüência de formato simples.Programa de exemplo:
fonte
new BigDecimal(doubleVar)
, como você pode ter problemas com arredondamento de pontos flutuantesdouble val = 265.335;
,BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.34
, mas(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.33
.Você também pode usar o
para garantir que você tenha os zeros à direita.
fonte
RoundingMode.
Decimal mode
usos padrãoRoundingMode.HALF_EVEN.
Como alguns outros observaram, a resposta correta é usar um
DecimalFormat
ouBigDecimal
. O ponto flutuante não possui casas decimais, portanto, você não pode arredondar / truncar para um número específico deles em primeiro lugar. Você tem que trabalhar em um radical decimal, e é isso que essas duas classes fazem.Estou postando o código a seguir como um contra-exemplo para todas as respostas neste segmento e, de fato, em todo StackOverflow (e em outros lugares) que recomendam multiplicação seguida de truncamento e divisão. Cabe aos defensores dessa técnica explicar por que o código a seguir produz a saída errada em mais de 92% dos casos.
Saída deste programa:
EDIT: Para endereçar alguns comentários abaixo, refiz a parte do módulo do loop de teste usando
BigDecimal
enew MathContext(16)
para a operação do módulo da seguinte maneira:Resultado:
fonte
100 trials 94 errors
Você deve começar com um teste aprovado e mostrar que a introdução do arredondamento interrompe o teste.double
como nenhum erro ideone.com/BVCHh3Suponha que você tenha
você pode usar
BigDecimal
ou sem BigDecimal
com ambas as soluções
d == 9232.13
fonte
RoundingMode.HALF_UP
está errada. Experimente com1.505
. O caminho certo é usarBigDecimal.valueOf(d)
.Você pode usar a classe DecimalFormat.
fonte
Double.valueOf()
foi escolhidoDouble.parseDouble()
? OvalueOf()
método retorna umDouble
objeto, enquantoparseDouble()
retornará umdouble
primitivo. Com a maneira como o código atual é gravado, você também aplica o desempacotamento automático ao retorno para convertê-lo no primitivo que suatwoDouble
variável espera, uma operação extra de bytecode. Eu mudaria a resposta para usar em seuparseDouble()
lugar.Double.parseDouble()
precisa deString
entrada.O Java How-to da Real publica essa solução, que também é compatível com versões anteriores ao Java 1.6.
fonte
fonte
Math.floor(x + 0.5)
eMath.round(x)
@Milhous: o formato decimal para arredondamento é excelente:
Eu acrescentaria que esse método é muito bom em fornecer um mecanismo de arredondamento numérico real - não apenas visualmente, mas também durante o processamento.
Hipotético: você precisa implementar um mecanismo de arredondamento em um programa GUI. Para alterar a exatidão / precisão de uma saída de resultado, basta alterar o formato de cursor (entre colchetes). De modo a:
retornaria como saída:
0.912385
retornaria como saída:
0.91239
retornaria como saída:
0.9124
[EDIT: também se o formato de sinal de intercalação for assim ("# 0. ############") e você digitar um decimal, por exemplo, 3.1415926, pelo argumento, DecimalFormat não produzirá nenhum lixo ( por exemplo, zeros à direita) e retornará:
3.1415926
.. se você estiver assim. Concedido, é um pouco detalhado para o gosto de alguns desenvolvedores - mas, ei, ele tem uma baixa presença de memória durante o processamento e é muito fácil de implementar.]Portanto, essencialmente, a beleza do DecimalFormat é que ele lida simultaneamente com a aparência da string - assim como com o nível de precisão do arredondamento. Ergo: você obtém dois benefícios pelo preço de uma implementação de código. ;)
fonte
double
. Use BigDecimal ou qualquer outro formato baseado em decimal.Aqui está um resumo do que você pode usar se desejar o resultado como String:
DecimalFormat # setRoundingMode () :
BigDecimal # setScale ()
Aqui está uma sugestão de quais bibliotecas você pode usar, se desejar
double
como resultado. Eu não o recomendaria para conversão de string, pois o double pode não ser capaz de representar exatamente o que você deseja (veja, por exemplo, aqui ):Precisão do Apache Commons Math
Funções da Colt
Utils de Weka
fonte
Você pode usar o seguinte método utilitário -
fonte
round(1.005,2);
ouround(0.50594724957626620092, 20);
Uma solução sucinta:
Consulte também https://stackoverflow.com/a/22186845/212950 Obrigado a jpdymond por oferecer isso.
fonte
Você pode usar BigDecimal
Consulte: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
fonte
Tente isto: org.apache.commons.math3.util.Precision.round (double x, int scale)
Consulte: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
A página inicial da Biblioteca de Matemática Apache Commons é: http://commons.apache.org/proper/commons-math/index.html
A implementação interna desse método é:
fonte
Como não encontrei resposta completa sobre esse tema, montei uma classe que deveria lidar com isso corretamente, com suporte para:
O uso é bem simples :
(Para o propósito deste exemplo, estou usando um código de idioma personalizado)
Aqui está a classe :
fonte
Se você realmente deseja números decimais para cálculo (e não apenas para saída), não use um formato de ponto flutuante baseado em binário como double.
Eu uso o BigDecimal para cálculos, mas lembre-se de que depende do tamanho dos números com os quais você está lidando. Na maioria das minhas implementações, acho que a análise de duplo ou inteiro para Long é suficiente para cálculos de números muito grandes.
De fato, recentemente usei o parsed-long para obter representações precisas (em oposição aos resultados hexadecimais) em uma GUI para números tão grandes quanto ################### ############### caracteres (como exemplo).
fonte
Para conseguir isso, podemos usar este formatador:
ou:
Use este método para obter sempre duas casas decimais:
Definindo esses valores:
Usando o método, podemos obter esses resultados:
demonstração online.
fonte
Apenas no caso de alguém ainda precisar de ajuda com isso. Esta solução funciona perfeitamente para mim.
retorna a
String
com a saída desejada.fonte
Concordo com a resposta escolhida para usar
DecimalFormat
--- ou alternativamenteBigDecimal
.Leia a atualização abaixo primeiro!
No entanto, se você não deseja arredondar o valor de casal e obter umdouble
resultado de valor, você pode usarorg.apache.commons.math3.util.Precision.round(..)
como mencionado acima. A implementação usaBigDecimal
, é lenta e cria lixo.Um método semelhante, mas rápido e sem lixo, é fornecido peloDoubleRounder
utilitário na biblioteca decimal4j:Saída
Consulte https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Isenção de responsabilidade: Estou envolvido no projeto decimal4j.
Atualização: como a @iaforek apontou, o DoubleRounder às vezes retorna resultados contra-intuitivos. O motivo é que ele executa arredondamentos matematicamente corretos. Por exemplo
DoubleRounder.round(256.025d, 2)
, será arredondado para 256,02 porque o valor duplo representado como 256,025d é um pouco menor que o valor racional 256,025 e, portanto, será arredondado para baixo.Notas:
BigDecimal(double)
construtor (mas não aovalueOf(double)
qual usa o construtor de cadeias).Por esses motivos e tudo mencionado acima neste post, não posso recomendar o uso do DoubleRounder .
fonte
O trecho de código abaixo mostra como exibir n dígitos. O truque é definir a variável pp como 1 seguida por n zeros. No exemplo abaixo, o valor da variável pp possui 5 zeros, portanto, 5 dígitos serão exibidos.
fonte
Se você estiver usando
DecimalFormat
para converterdouble
paraString
, é muito simples:Existem vários
RoundingMode
valores de enumeração para selecionar, dependendo do comportamento necessário.fonte
Eu vim aqui apenas querendo uma resposta simples sobre como arredondar um número. Esta é uma resposta suplementar para fornecer isso.
Como arredondar um número em Java
O caso mais comum é usar
Math.round()
.Os números são arredondados para o número inteiro mais próximo. Um
.5
valor é arredondado para cima. Se você precisar de um comportamento de arredondamento diferente daquele, poderá usar uma das outras funções matemáticas . Veja a comparação abaixo.volta
Como mencionado acima, isso arredonda para o número inteiro mais próximo.
.5
decimais arredondados para cima. Este método retorna umint
.teto
Qualquer valor decimal é arredondado para o próximo número inteiro. Vai para o teto . Este método retorna a
double
.chão
Qualquer valor decimal é arredondado para o próximo número inteiro. Este método retorna a
double
.rint
É semelhante ao arredondamento nos valores decimais, arredondado para o número inteiro mais próximo. No entanto, diferentemente
round
, os.5
valores são arredondados para o número par. Este método retorna adouble
.fonte
Se você estiver usando uma tecnologia que possui um JDK mínimo. Aqui está uma maneira sem nenhuma biblioteca Java:
fonte
DecimalFormat é a melhor maneira de produzir, mas eu não prefiro. Eu sempre faço isso o tempo todo, porque retorna o valor duplo. Para que eu possa usá-lo mais do que apenas produzir.
OU
Se você precisar de um valor grande de casas decimais, poderá usar BigDecimal. De qualquer forma
.0
é importante. Sem ele, o arredondamento de 0,33333d5 retorna 0,33333 e apenas 9 dígitos são permitidos. A segunda função sem.0
problemas com 0,30000 retorna 0,30000000000000004.fonte
aqui está a minha resposta:
fonte
Então, depois de ler a maioria das respostas, percebi que a maioria delas não será precisa, na verdade, usar
BigDecimal
parece ser a melhor escolha, mas se você não entender como as coisasRoundingMode
funcionam, inevitavelmente perderá a precisão. Eu descobri isso ao trabalhar com grandes números em um projeto e pensei que poderia ajudar outras pessoas com problemas para arredondar números. Por exemplo.Você esperaria obter
1363.28
uma saída, mas acabará com o1363.27
que não é esperado, se não souber o queRoundingMode
está fazendo. Então, olhando para o Oracle Docs , você encontrará a seguinte descrição paraRoundingMode.HALF_UP
.Então, sabendo disso, percebemos que não obteríamos um arredondamento exato, a menos que desejássemos arredondar para o vizinho mais próximo . Portanto, para realizar uma rodada adequada, precisaríamos fazer um loop do
n-1
decimal para os dígitos decimais desejados. Por exemplo.Isso acabará nos dando o resultado esperado, o que seria
1363.28
.fonte
Onde dp = casa decimal você deseja e o valor é um dobro.
fonte
1.0
paravalue = 1.005
edp = 2
. Use isso em seu lugar.Lembre-se de que String.format () e DecimalFormat produzem string usando o Locale padrão. Portanto, eles podem escrever um número formatado com ponto ou vírgula como um separador entre partes inteiras e decimais. Para garantir que a String arredondada esteja no formato que você deseja, use java.text.NumberFormat da seguinte forma:
Será impressa na localidade em inglês (independentemente da localidade): 0,99 123,57 123,00
O exemplo é retirado de Farenda - como converter o dobro para o String corretamente .
fonte
Em geral, o arredondamento é feito pela escala:
round(num / p) * p
fonte