Um duplo de 64 bits pode representar inteiro +/- 2 53 exatamente
Dado esse fato, optei por usar um tipo duplo como um tipo único para todos os meus tipos, pois meu maior número inteiro é sem sinal de 32 bits.
Mas agora eu tenho que imprimir esses pseudo números inteiros, mas o problema é que eles também são misturados com dobras reais.
Então, como faço para imprimir essas dobras muito bem em Java?
Eu tentei String.format("%f", value)
, que está próximo, exceto que recebo muitos zeros à direita para valores pequenos.
Aqui está um exemplo de saída de %f
232.00000000 0.18000000000 1237875192.0 4.5800000000 0,00000000 1.23450000
O que eu quero é:
232 0,18 1237875192 4.58 0 0 1,2345
Claro que posso escrever uma função para cortar esses zeros, mas isso representa muita perda de desempenho devido à manipulação de String. Posso fazer melhor com outro código de formato?
EDITAR
As respostas de Tom E. e Jeremy S. são inaceitáveis, pois ambas arbitrariamente arredondam para duas casas decimais. Por favor, entenda o problema antes de responder.
EDIT 2
Observe que String.format(format, args...)
depende da localidade (consulte as respostas abaixo).
System.out.println("YOUR STRING" + YOUR_DOUBLE_VARIABLE);
Respostas:
Se a ideia é imprimir números inteiros armazenados como dobra como se fossem números inteiros, e imprimir os dobros com a precisão mínima necessária:
Produz:
E não depende da manipulação de strings.
fonte
double
maior que o máximoint
. Mesmo comlong
isso ainda falharia com grandes números. Além disso, retornará uma String em forma exponencial, por exemplo, "1.0E10", para valores grandes, o que provavelmente não é o que o solicitante deseja. Use em%f
vez de%s
na segunda sequência de formato para corrigir isso.%f
. A resposta é específica para a situação descrita e a saída desejada. O OP sugeriu que seu valor máximo era um int sem sinal de 32 bits, o que eu entendi comoint
aceitável (não assinado não existe realmente em Java e nenhum exemplo era problemático), mas mudarint
paralong
é uma correção trivial se a situação for diferente.String.format("%s",d)
??? Fale sobre despesas desnecessárias. UseDouble.toString(d)
. Mesmo para o outro:Long.toString((long)d)
.%s
não funciona com localidades. Em alemão, usamos um "," em vez de um "." em números decimais. EnquantoString.format(Locale.GERMAN, "%f", 1.5)
retorna "1.500000",String.format(Locale.GERMAN, "%s", 1.5)
retorna "1.5" - com um ".", Que é falso no idioma alemão. Também existe uma versão dependente de localidade de "% s"?Como apontado nos comentários, esta não é a resposta certa para a pergunta original.
Dito isto, é uma maneira muito útil de formatar números sem zeros à direita desnecessários.
fonte
fonte
Em resumo:
Se você quiser se livrar dos zeros à direita e dos problemas de localidade, use:
Explicação:
Por que outras respostas não me agradaram:
Double.toString()
ouSystem.out.println
ouFloatingDecimal.toJavaFormatString
usa notações científicas se o dobro for menor que 10 ^ -3 ou maior que ou igual a 10 ^ 7usando
%f
, a precisão decimal padrão é 6; caso contrário, você pode codificá-la, mas isso resultará em zeros extras adicionados se você tiver menos casas decimais. Exemplo:usando
setMaximumFractionDigits(0);
ou%.0f
removendo qualquer precisão decimal, o que é bom para números inteiros / longos, mas não para o dobrousando DecimalFormat, você depende localmente. Na localidade francesa, o separador decimal é uma vírgula, não um ponto:
O uso da localidade ENGLISH garante que você obtenha um ponto para o separador decimal, onde quer que o seu programa seja executado
Por que usar 340 então para
setMaximumFractionDigits
?Duas razões :
setMaximumFractionDigits
aceita um número inteiro, mas sua implementação tem um número máximo permitido dosDecimalFormat.DOUBLE_FRACTION_DIGITS
quais é igual a 340Double.MIN_VALUE = 4.9E-324
portanto, com 340 dígitos, você não deve arredondar sua precisão dupla e soltafonte
0
vez de#.
DecimalFormat.DOUBLE_FRACTION_DIGITS
mas o valor 340, que fornece um comentário para mostrar que é igualDecimalFormat.DOUBLE_FRACTION_DIGITS
. Por que não usar apenas a constante ???Por que não:
Isso deve funcionar com os valores extremos suportados pelo Double. Rendimentos:
fonte
"%s"
basicamente chama,d.toString()
mas não funciona comint
ou sed==null
!Na minha máquina, a seguinte função é aproximadamente 7 vezes mais rápida que a função fornecida pela resposta de JasonD , pois evita
String.format
:fonte
Meus 2 centavos:
fonte
return String.format(Locale.US, (n % 1 == 0 ? "%.0f" : "%.1f"), n);
.Não, não importa.
A perda de desempenho devido à manipulação de String é zero.
E aqui está o código para aparar o final depois
%f
fonte
Use um
DecimalFormat
esetMinimumFractionDigits(0)
fonte
setMaximumFractionDigits(2)
esetGroupingUsed(false)
(os OP não mencionam, mas a partir do exemplo, parece que é necessário). Além disso, um pequeno caso de teste não dói, pois é trivial nesse caso. Ainda assim, desde que eu acho que a sua a solução mais simples, uma upvote é um upvote :)fonte
Observe que
String.format(format, args...)
depende da localidade porque formata usando a localidade padrão do usuário, ou seja, provavelmente com vírgulas e até espaços dentro, como 123 456,789 ou 123,456.789 , o que pode não ser exatamente o que você espera.Você pode preferir usar
String.format((Locale)null, format, args...)
.Por exemplo,
impressões
e é isso que vai
String.format(format, args...)
em diferentes países.EDIT Ok, já que houve uma discussão sobre formalidades:
fonte
Eu fiz um
DoubleFormatter
para converter eficientemente um grande número de valores duplos em uma String agradável / apresentável:Aqui o código:
Nota: usei 2 funções da biblioteca GUAVA. Se você não usa o GUAVA, codifique você mesmo:
fonte
Este fará o trabalho bem, sei que o tópico é antigo, mas estava lutando com o mesmo problema até chegar a esse ponto. Espero que alguém ache útil.
fonte
fonte
fonte
Resposta tardia, mas ...
Você disse que escolhe armazenar seus números com o tipo duplo . Eu acho que isso pode ser a raiz do problema, porque obriga a armazenar números inteiros em duplas (e, portanto, perdendo as informações iniciais sobre a natureza do valor). Que tal armazenar seus números nas instâncias do Number classe (superclasse de Duplo e Inteiro) e confiar no polimorfismo para determinar o formato correto de cada número?
Eu sei que pode não ser aceitável refatorar uma parte inteira do seu código devido a isso, mas pode produzir a saída desejada sem código / conversão / análise extra.
Exemplo:
Produzirá a seguinte saída:
fonte
Isto é o que eu vim com:
Um liner simples, só lança para int se realmente precisar
fonte
Formate o preço com agrupamento, arredondamento, sem zeros desnecessários (em dobro).
Regras:
2.0000 = 2; 1.0100000 = 1.01
)2.010 = 2.01; 0.20 = 0.2
)1.994 = 1.99; 1.995 = 2; 1.006 = 1.01; 0.0006 -> 0
)0
(null/-0 = 0
)$
(= $56/-$56
)101101.02 = $101,101.02
)Mais exemplos:
Escrito em Kotlin como uma divertida extensão do Double (causa usada no Android), mas pode ser convertido para Java facilmente, pois classes java foram usadas.
Como usar:
Sobre o DecimalFormat : https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
fonte
Eu tive que usar essa causa
d == (long)d
estava me dando violação no relatório do sonarfonte
este é o resultado de alguns testes:
fonte
Aqui estão duas maneiras de conseguir isso. Primeiro, a maneira mais curta (e provavelmente melhor):
E aqui está a maneira mais longa e provavelmente pior:
fonte
Para o Kotlin, você pode usar extensões como:
fonte
Aqui está outra resposta que tem uma opção para acrescentar decimal SOMENTE SE decimal não for zero.
fonte
Aqui está uma resposta que realmente funciona (combinação de respostas diferentes aqui)
fonte
Eu sei que esse é um tópico muito antigo. Mas acho que a melhor maneira de fazer isso é como abaixo:
Resultado:
O único problema é o último em que .0 não é removido. Mas se você é capaz de conviver com isso, isso funciona melhor. % .2f arredondará para os últimos 2 dígitos decimais. DecimalFormat também. Se você precisar de todas as casas decimais, mas não os zeros à direita, isso funcionará melhor.
fonte
System.out.println(new java.text.DecimalFormat("#.##").format(1.0005));
será impresso1
Isso fará com que a string solte os 0-s restantes.
fonte