Format de numéro de devise Java

89

Existe-t-il un moyen de formater un décimal comme suit:

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

S'il s'agit d'un nombre rond, omettez la partie décimale. Sinon, formatez avec deux décimales.

DD.
la source

Réponses:

48

J'en doute. Le problème est que 100 n'est jamais 100 si c'est un flottant, c'est normalement 99,9999999999 ou 100,0000001 ou quelque chose comme ça.

Si vous voulez le formater de cette façon, vous devez définir un epsilon, c'est-à-dire une distance maximale d'un nombre entier, et utiliser le formatage entier si la différence est plus petite, et un flottant sinon.

Quelque chose comme ça ferait l'affaire:

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
  }
}
extraneon
la source
8
Petit pinaillage: un flottant peut être exactement 100, avec un motif de bits 0x42c80000.
Karol S
2
Oui, comme l'a déclaré Karol S, de nombreux nombres PEUVENT être exactement appariés par des flotteurs. Mais pas TOUS les numéros. 100 est un nombre qui peut être représenté, vous devez juste tenir compte des nombres qui ne peuvent pas l'être.
csga5000
160

Je recommanderais d'utiliser le package java.text:

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

Cela présente l'avantage supplémentaire d'être spécifique aux paramètres régionaux.

Mais, si vous le devez, tronquez la chaîne que vous récupérez si c'est un dollar entier:

if (moneyString.endsWith(".00")) {
    int centsIndex = moneyString.lastIndexOf(".00");
    if (centsIndex != -1) {
        moneyString = moneyString.substring(1, centsIndex);
    }
}
duffymo
la source
17
Vous ne devez jamais utiliser un double pour représenter les devises. Convertissez-vous en longs et gérez vous-même la virgule décimale ou utilisez-le BigDecimalavec un formateur. joda-money.sourceforge.net devrait être une bonne bibliothèque à utiliser une fois que c'est fait.
gpampara
5
Je suis d'accord re: double! = Argent, mais ce n'est pas ainsi que la question a été posée.
duffymo
3
Que voulez-vous dire par comment fonctionnent les devises? Je peux dire que quelque chose coûte 1 $ et non 1,00 $ .... il existe différentes manières d'afficher les devises (autre que la valeur par défaut) et cette question demande comment omettre la partie décimale si c'est un nombre entier.
DD.
1
C'est un problème de rendu. Mettez la logique dans votre interface utilisateur pour accepter la devise en tant que chaîne et tronquer la décimale et les cents s'il s'agit d'un dollar exact.
duffymo
2
D'accord - c'est pourquoi j'ai recommandé d'utiliser Locale lorsque j'ai écrit ceci il y a 5,5 ans. "Mais, si vous devez, ..." est la phrase clé.
duffymo le
124
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));

La meilleure façon d'afficher la devise

Production

200,00 $

Si vous ne souhaitez pas utiliser de signe, utilisez cette méthode

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

200,00

Cela peut également être utilisé (avec le séparateur de milliers)

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

2 000 000,00

Thilina Dharmasena
la source
Il ne semble pas que la "devise" soit référencée ou utilisée après sa déclaration ... y a-t-il un effet secondaire de la ligne 3? Ou une raison pour laquelle vous l'avez inclus?
Damian
En savoir plus sur [Class Locale] [1] [1]: docs.oracle.com/javase/7/docs/api/java/util/…
Thilina Dharmasena
18

Je n'ai pas trouvé de bonne solution après une recherche sur Google, il suffit de poster ma solution pour que d'autres puissent s'y référer. utilisez priceToString pour formater l'argent.

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
la source
Il n'a jamais dit que c'était meilleur. IL vient de publier sa solution pour que d'autres puissent s'y référer. Le moins que vous puissiez dire, c'est un merci.
Umang Desai
Et si je souhaite afficher le prix au format indien. Sans décimales. Format -> ##, ##, ###
Bhuvan
À la méthode priceWithDecimal (Double), essayez de changer le masque "###,###,###.00"pour "###,###,##0.00"afficher "0,00" lorsque la valeur est "0"
dellasavia
1
Qu'est-ce que l'inverse pour convertir à nouveau la devise formatée en Double
Vivek Shankar
6

Oui. Vous pouvez utiliser java.util.formatter . Vous pouvez utiliser une chaîne de mise en forme telle que "% 10.2f"

dj_segfault
la source
String.format()est un bon wrapper statique pour cela. Je ne sais pas pourquoi vous utilisez «10», cependant.
Xr.
N'ayant aucune indication sur la taille du nombre, j'ai choisi 10 Ex Recto. Nous ne savons pas si c'est le prix d'une friandise ou d'une voiture. Je crois que vous pouvez aussi simplement faire "% .2f" pour laisser la taille totale illimitée.
dj_segfault
DD voulait que la partie décimale soit omise, si le montant est un nombre arrondi d'unités monétaires.
jarnbjo
6

J'utilise celui-ci (en utilisant StringUtils de commons-lang):

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

Vous ne devez vous occuper que des paramètres régionaux et de la chaîne correspondante à couper.

Dirk Lachowski
la source
5

Je pense que c'est simple et clair pour imprimer une devise:

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

produit: 12 345,68 $

Et l'une des solutions possibles à la question:

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

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

Production:

100

100,10

Andrew
la source
Vous avez manqué le point du message. Si le nombre est un nombre entier, je ne veux pas afficher de décimales.
DD.
DD. Je suis désolé, et j'ai corrigé la réponse en fonction de la question.
Andrew
5

Nous aurons généralement besoin de faire l'inverse, si votre champ json money est un float, il peut être 3.1, 3.15 ou juste 3.

Dans ce cas, vous devrez peut-être l'arrondir pour un affichage correct (et pour pouvoir utiliser un masque sur un champ de saisie plus tard):

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));
s'affaisse
la source
5

cette meilleure façon de faire cela.

    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
la source
5
NumberFormat currency = NumberFormat.getCurrencyInstance();
String myCurrency = currency.format(123.5);
System.out.println(myCurrency);

production:

$123.50

Si vous souhaitez changer de devise,

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

production:

123.50
Subhashi
la source
4

vous devriez faire quelque chose comme ceci:

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);
}

qui imprime:

100

100,10

Stefan De Boey
la source
Math.round (d)! = D fonctionnera-t-il? Avec flotte souvent! = Même si vous pensez que c'est le cas.
extraneon
1
dans l'autre sens, si d était 100,000000000000001, il serait toujours imprimé comme 100
Stefan De Boey
4

Je sais que c'est une vieille question mais ...

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
la source
3
Cela ne fonctionne pas, il fait 100.1 -> "100.1" par exemple - voir stackoverflow.com/questions/5033404/…
davnicwil
4

Vous pouvez simplement faire quelque chose comme ça et passer le nombre entier, puis les cents après.

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

Je suis d'accord avec @duffymo pour dire que vous devez utiliser les java.text.NumberFormatméthodes pour ce genre de choses. Vous pouvez en fait faire tout le formatage nativement sans faire de comparaison de String vous-même:

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

Quelques bits pour souligner:

  • L'ensemble ne Math.round(priceAsDouble * 100) % 100fait que contourner les inexactitudes des doubles / flotteurs. En gros, il suffit de vérifier si nous arrondissons à la centaine (c'est peut-être un biais américain) qu'il reste des cents.
  • L'astuce pour supprimer les décimales est la setMaximumFractionDigits()méthode

Quelle que soit votre logique pour déterminer si les décimales doivent être tronquées ou non, elle setMaximumFractionDigits()doit être utilisée.

xbakesx
la source
1
En ce qui concerne votre point de vue *100et d' %100être biaisé par les États-Unis, vous pouvez utiliser Math.pow(10, formatter.getMaximumFractionDigits())au lieu d'un codé 100en dur pour utiliser le nombre correct pour la locale ...
daiscog
3

Si vous voulez travailler sur les devises, vous devez utiliser la classe BigDecimal. Le problème est qu'il n'y a aucun moyen de stocker des nombres flottants en mémoire (par exemple, vous pouvez stocker 5.3456, mais pas 5.3455), ce qui peut avoir des effets sur de mauvais calculs.

Il y a un bel article sur la manière de coopérer avec BigDecimal et les devises:

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

Adrian Adamczyk
la source
2
Cela n'a aucun rapport avec la question que j'ai posée.
DD.
3

Format de 1000000,2 à 1000000,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
la source
2

Ce message m'a vraiment aidé à obtenir enfin ce que je veux. Donc je voulais juste apporter mon code ici pour aider les autres. Voici mon code avec quelques explications.

Le code suivant:

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

Reviendra:

5,-
€ 5,50

La méthode jeroensFormat () actuelle:

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;
        }
}

La méthode displayJeroensFormat qui appelle la méthode 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
    }

Aura la sortie suivante:

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

Ce code utilise votre devise actuelle. Dans mon cas, c'est Hollande, donc la chaîne formatée pour moi sera différente de celle pour quelqu'un aux États-Unis.

  • Hollande: 999.999,99
  • États-Unis: 999 999,99

Regardez simplement les 3 derniers caractères de ces nombres. Mon code a une instruction if pour vérifier si les 3 derniers caractères sont égaux à ", 00". Pour l'utiliser aux États-Unis, vous devrez peut-être le changer en ".00" si cela ne fonctionne pas déjà.

Jeroen
la source
2

J'étais assez fou pour écrire ma propre fonction:

Cela convertira l'entier au format monétaire (peut également être modifié pour les décimales):

 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
la source
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
la source
1

C'est ce que j'ai fait, en utilisant un entier pour représenter le montant en cents à la place:

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);
}

Le problème NumberFormat.getCurrencyInstance()est que parfois vous voulez vraiment que 20 $ soient 20 $, cela semble juste mieux que 20,00 $.

Si quelqu'un trouve une meilleure façon de faire cela, en utilisant NumberFormat, je suis toute oreille.

Viktor Nordling
la source
1

Pour les personnes qui souhaitent formater la devise, mais ne veulent pas qu'elle soit basée sur le local, nous pouvons le faire:

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
la source