Formato de número de moeda Java

91

Existe uma maneira de formatar um decimal da seguinte forma:

100   -> "100"  
100.1 -> "100.10"

Se for um número redondo, omita a parte decimal. Caso contrário, formate com duas casas decimais.

DD.
fonte

Respostas:

48

Eu duvido. O problema é que 100 nunca é 100 se for um float, normalmente é 99,9999999999 ou 100,0000001 ou algo parecido.

Se você quiser formatar dessa forma, terá que definir um épsilon, ou seja, uma distância máxima de um número inteiro, e usar a formatação inteira se a diferença for menor, e um float caso contrário.

Algo como isso resolveria o problema:

public String formatDecimal(float number) {
  float epsilon = 0.004f; // 4 tenths of a cent
  if (Math.abs(Math.round(number) - number) < epsilon) {
     return String.format("%10.0f", number); // sdb
  } else {
     return String.format("%10.2f", number); // dj_segfault
  }
}
extrânon
fonte
8
Pequenos detalhes: um float pode ser exatamente 100, com padrão de bits 0x42c80000.
Karol S de
2
Sim, como foi afirmado por Karol S, muitos números PODEM ser correspondidos exatamente por flutuadores. Só não TODOS os números. 100 é um número que pode ser representado, você deve considerar apenas os números que não podem ser.
csga5000
160

Eu recomendo usar o pacote java.text:

double money = 100.1;
NumberFormat formatter = NumberFormat.getCurrencyInstance();
String moneyString = formatter.format(money);
System.out.println(moneyString);

Isso tem a vantagem adicional de ser específico do local.

Mas, se necessário, trunque a string que você recebe de volta se for um dólar inteiro:

if (moneyString.endsWith(".00")) {
    int centsIndex = moneyString.lastIndexOf(".00");
    if (centsIndex != -1) {
        moneyString = moneyString.substring(1, centsIndex);
    }
}
duffymo
fonte
17
Você nunca deve usar um duplo para representar moedas. Converta em longos e gerencie o ponto decimal você mesmo ou use BigDecimalcom um formatador. joda-money.sourceforge.net deve ser uma boa biblioteca para usar quando estiver pronto.
gpampara
5
Eu concordo re: double! = Money, mas não foi assim que a pergunta foi feita.
duffymo
3
O que você quer dizer com isso é como as moedas funcionam? Posso dizer que algo custa $ 1, não $ 1,00 ... existem maneiras diferentes de exibir moedas (além do padrão) e esta questão pergunta como omitir a parte decimal se for um número inteiro.
DD.
1
É um problema de renderização. Coloque a lógica em sua IU para aceitar a moeda como uma string e truncar o decimal e os centavos se for um dólar exato.
duffymo
2
Concordo - é por isso que recomendei usar o Locale quando escrevi isto há 5,5 anos. "Mas, se for preciso, ...." é a frase-chave.
duffymo
126
double amount =200.0;
Locale locale = new Locale("en", "US");      
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
System.out.println(currencyFormatter.format(amount));

ou

double amount =200.0;
System.out.println(NumberFormat.getCurrencyInstance(new Locale("en", "US"))
        .format(amount));

A melhor maneira de exibir moeda

Resultado

$ 200,00

Se você não quiser usar sinal, use este método

double amount = 200;
DecimalFormat twoPlaces = new DecimalFormat("0.00");
System.out.println(twoPlaces.format(amount));

200,00

Isso também pode ser usado (com o separador de milhar)

double amount = 2000000;    
System.out.println(String.format("%,.2f", amount));          

2.000.000,00

Thilina Dharmasena
fonte
Não parece que a "moeda" é referenciada ou usada após ser declarada ... há um efeito colateral da linha 3? Ou alguma razão para você incluí-lo?
Damian
Leia mais sobre [Class Locale] [1] [1]: docs.oracle.com/javase/7/docs/api/java/util/…
Thilina Dharmasena
18

Não achei nenhuma solução boa após a busca no google, apenas poste minha solução para outra referência. use priceToString para formatar dinheiro.

public static String priceWithDecimal (Double price) {
    DecimalFormat formatter = new DecimalFormat("###,###,###.00");
    return formatter.format(price);
}

public static String priceWithoutDecimal (Double price) {
    DecimalFormat formatter = new DecimalFormat("###,###,###.##");
    return formatter.format(price);
}

public static String priceToString(Double price) {
    String toShow = priceWithoutDecimal(price);
    if (toShow.indexOf(".") > 0) {
        return priceWithDecimal(price);
    } else {
        return priceWithoutDecimal(price);
    }
}
wu liang
fonte
Ele nunca disse que é melhor. ELE acabou de postar sua solução para que outros possam consultá-la. O mínimo que você poderia dizer é um obrigado.
Umang Desai
1
E se eu quiser exibir o preço no formato indiano. Sem decimais. Formato -> ##, ##, ###
Bhuvan
No método priceWithDecimal (Double), tente alterar a máscara "###,###,###.00"para "###,###,##0.00"mostrar "0,00" quando o valor for "0"
dellasavia
1
o que será o contrário ao converter a moeda formatada para o dobro novamente
Vivek Shankar
6

Sim. Você pode usar java.util.formatter . Você pode usar uma string de formatação como "% 10.2f"

dj_segfault
fonte
String.format()é um bom wrapper estático para isso. Não sei por que você usa '10', no entanto.
Xr.
Sem orientação sobre o tamanho do número, escolhi 10 Ex Recto. Não sabemos se este é o preço de uma barra de chocolate ou de um carro. Eu acredito que você também pode simplesmente fazer "% .2f" para deixar o tamanho total ilimitado.
dj_segfault
DD queria que a parte decimal fosse omitida, se o valor for um número redondo de unidades monetárias.
jarnbjo
6

Estou usando este (usando StringUtils de commons-lang):

Double qty = 1.01;
String res = String.format(Locale.GERMANY, "%.2f", qty);
String fmt = StringUtils.removeEnd(res, ",00");

Você só deve cuidar da localidade e da String correspondente para cortar.

Dirk Lachowski
fonte
5

Acho que isso é simples e claro para imprimir uma moeda:

DecimalFormat df = new DecimalFormat("$###,###.##"); // or pattern "###,###.##$"
System.out.println(df.format(12345.678));

produção: $ 12.345,68

E uma das soluções possíveis para a questão:

public static void twoDecimalsOrOmit(double d) {
    System.out.println(new DecimalFormat(d%1 == 0 ? "###.##" : "###.00").format(d));
}

twoDecimalsOrOmit((double) 100);
twoDecimalsOrOmit(100.1);

Resultado:

100

100,10

Andrew
fonte
Você perdeu o ponto da postagem. Se o número for um número inteiro, não desejo exibir decimais.
DD.
DD. Sinto muito, e corrigi a resposta de acordo com a pergunta.
Andrew
5

Normalmente precisaremos fazer o inverso, se o seu campo de dinheiro json for um float, pode vir como 3.1, 3.15 ou apenas 3.

Neste caso, você pode precisar arredondá-lo para uma exibição adequada (e para poder usar uma máscara em um campo de entrada posteriormente):

floatvalue = 200.0; // it may be 200, 200.3 or 200.37, BigDecimal will take care
Locale locale = new Locale("en", "US");      
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);

BigDecimal valueAsBD = BigDecimal.valueOf(value);
    valueAsBD.setScale(2, BigDecimal.ROUND_HALF_UP); // add digits to match .00 pattern

System.out.println(currencyFormatter.format(amount));
sagits
fonte
5

esta é a melhor maneira de fazer isso.

    public static String formatCurrency(String amount) {
        DecimalFormat formatter = new DecimalFormat("###,###,##0.00");
        return formatter.format(Double.parseDouble(amount));
    }

100 -> "100,00"
100,1 -> "100,10"

Samet ÖZTOPRAK
fonte
5
NumberFormat currency = NumberFormat.getCurrencyInstance();
String myCurrency = currency.format(123.5);
System.out.println(myCurrency);

resultado:

$123.50

Se você quiser mudar a moeda,

NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CHINA);
String myCurrency = currency.format(123.5);
System.out.println(myCurrency);

resultado:

123.50
Subhashi
fonte
4

você deve fazer algo assim:

public static void main(String[] args) {
    double d1 = 100d;
    double d2 = 100.1d;
    print(d1);
    print(d2);
}

private static void print(double d) {
    String s = null;
    if (Math.round(d) != d) {
        s = String.format("%.2f", d);
    } else {
        s = String.format("%.0f", d);
    }
    System.out.println(s);
}

que imprime:

100

100,10

Stefan De Boey
fonte
O Math.round (d)! = D funcionará? Com flutuadores, muitas vezes! = Mesmo que você pense que é.
extrânon
1
do outro modo, se d fosse 100,000000000000001, então ainda seria impresso como 100
Stefan De Boey
4

Eu sei que esta é uma pergunta antiga, mas ...

import java.text.*;

public class FormatCurrency
{
    public static void main(String[] args)
    {
        double price = 123.4567;
        DecimalFormat df = new DecimalFormat("#.##");
        System.out.print(df.format(price));
    }
}
Aezur
fonte
3
Isso não funciona, ele faz 100,1 -> "100,1" por exemplo - consulte stackoverflow.com/questions/5033404/…
davnicwil
4

Você pode simplesmente fazer algo assim e passar o número inteiro e depois os centavos.

String.format("$%,d.%02d",wholeNum,change);
user2645904
fonte
4

Eu concordo com @duffymo que você precisa usar os java.text.NumberFormatmétodos para esse tipo de coisas. Na verdade, você pode fazer toda a formatação nativamente sem fazer nenhuma comparação de String:

private String formatPrice(final double priceAsDouble) 
{
    NumberFormat formatter = NumberFormat.getCurrencyInstance();
    if (Math.round(priceAsDouble * 100) % 100 == 0) {
        formatter.setMaximumFractionDigits(0);
    }
    return formatter.format(priceAsDouble);
}

Algumas coisas para apontar:

  • O todo Math.round(priceAsDouble * 100) % 100 é apenas contornar as imprecisões de duplos / flutuantes. Basicamente, apenas verificando se arredondamos para a casa das centenas (talvez seja um viés dos EUA), há centavos restantes.
  • O truque para remover os decimais é o setMaximumFractionDigits()método

Qualquer que seja sua lógica para determinar se os decimais devem ou não ser truncados, setMaximumFractionDigits()deve ser usada.

xbakesx
fonte
1
Re a sua opinião sobre o *100e %100sendo tendencioso dos EUA, você poderia usar em Math.pow(10, formatter.getMaximumFractionDigits())vez de um codificado 100para usar o número correto para o local ...
daiscog
3

Se você quer trabalhar com moedas, tem que usar a classe BigDecimal. O problema é que não há como armazenar alguns números flutuantes na memória (por exemplo, você pode armazenar 5,3456, mas não 5,3455), o que pode afetar cálculos ruins.

Há um bom artigo sobre como cooperar com BigDecimal e moedas:

http://www.javaworld.com/javaworld/jw-06-2001/jw-0601-cents.html

Adrian Adamczyk
fonte
2
Isso é completamente irrelevante para a pergunta que fiz.
DD.
3

Formato de 1000000,2 a 1 000 000,20

private static final DecimalFormat DF = new DecimalFormat();

public static String toCurrency(Double d) {
    if (d == null || "".equals(d) || "NaN".equals(d)) {
        return " - ";
    }
    BigDecimal bd = new BigDecimal(d);
    bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
    DecimalFormatSymbols symbols = DF.getDecimalFormatSymbols();
    symbols.setGroupingSeparator(' ');
    String ret = DF.format(bd) + "";
    if (ret.indexOf(",") == -1) {
        ret += ",00";
    }
    if (ret.split(",")[1].length() != 2) {
        ret += "0";
    }
    return ret;
}
Lukas
fonte
2

Esse post realmente me ajudou a finalmente conseguir o que desejo. Então, eu só queria contribuir com meu código aqui para ajudar outras pessoas. Aqui está meu código com algumas explicações.

O seguinte código:

double moneyWithDecimals = 5.50;
double moneyNoDecimals = 5.00;
System.out.println(jeroensFormat(moneyWithDecimals));
System.out.println(jeroensFormat(moneyNoDecimals));

Retornará:

5,-
€ 5,50

O método jeroensFormat () real:

public String jeroensFormat(double money)//Wants to receive value of type double
{
        NumberFormat dutchFormat = NumberFormat.getCurrencyInstance();
        money = money;
        String twoDecimals = dutchFormat.format(money); //Format to string
        if(tweeDecimalen.matches(".*[.]...[,]00$")){
            String zeroDecimals = twoDecimals.substring(0, twoDecimals.length() -3);
                return zeroDecimals;
        }
        if(twoDecimals.endsWith(",00")){
            String zeroDecimals = String.format("€ %.0f,-", money);
            return zeroDecimals; //Return with ,00 replaced to ,-
        }
        else{ //If endsWith != ,00 the actual twoDecimals string can be returned
            return twoDecimals;
        }
}

O método displayJeroensFormat que chama o método jeroensFormat ()

    public void displayJeroensFormat()//@parameter double:
    {
        System.out.println(jeroensFormat(10.5)); //Example for two decimals
        System.out.println(jeroensFormat(10.95)); //Example for two decimals
        System.out.println(jeroensFormat(10.00)); //Example for zero decimals
        System.out.println(jeroensFormat(100.000)); //Example for zero decimals
    }

Terá a seguinte saída:

10,5010,9510,-
€ 100.000 (In Holland numbers bigger than € 999,- and wit no decimals don't have ,-)

Este código usa sua moeda atual. No meu caso, é a Holanda, então a string formatada para mim será diferente do que para alguém nos EUA.

  • Holanda: 999.999,99
  • US: 999.999,99

Observe os últimos 3 caracteres desses números. Meu código tem uma declaração if para verificar se os últimos 3 caracteres são iguais a ", 00". Para usar isso nos EUA, você pode ter que mudar para ".00" se ainda não funcionar.

Jeroen
fonte
2

Eu fui louco o suficiente para escrever minha própria função:

Isso converterá o formato inteiro para moeda (pode ser modificado para decimais também):

 String getCurrencyFormat(int v){
        String toReturn = "";
        String s =  String.valueOf(v);
        int length = s.length();
        for(int i = length; i >0 ; --i){
            toReturn += s.charAt(i - 1);
            if((i - length - 1) % 3 == 0 && i != 1) toReturn += ',';
        }
        return "$" + new StringBuilder(toReturn).reverse().toString();
    }
A-Sharabiani
fonte
2
  public static String formatPrice(double value) {
        DecimalFormat formatter;
        if (value<=99999)
          formatter = new DecimalFormat("###,###,##0.00");
        else
            formatter = new DecimalFormat("#,##,##,###.00");

        return formatter.format(value);
    }
PRATEEK BHARDWAJ
fonte
2

Para as pessoas que desejam formatar a moeda, mas não querem que seja baseada no local, podemos fazer o seguinte:

val numberFormat = NumberFormat.getCurrencyInstance() // Default local currency
val currency = Currency.getInstance("USD")            // This make the format not locale specific 
numberFormat.setCurrency(currency)

...use the formator as you want...
Haomin
fonte
1

Isso é o que eu fiz, usando um número inteiro para representar o valor em centavos:

public static String format(int moneyInCents) {
    String format;
    Number value;
    if (moneyInCents % 100 == 0) {
        format = "%d";
        value = moneyInCents / 100;
    } else {
        format = "%.2f";
        value = moneyInCents / 100.0;
    }
    return String.format(Locale.US, format, value);
}

O problema com NumberFormat.getCurrencyInstance() é que às vezes você realmente quer $ 20 como $ 20, mas parece melhor do que $ 20,00.

Se alguém encontrar uma maneira melhor de fazer isso, usando NumberFormat, sou todo ouvidos.

Viktor Nordling
fonte