Java-Währungsnummernformat

87

Gibt es eine Möglichkeit, eine Dezimalstelle wie folgt zu formatieren:

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

Wenn es sich um eine runde Zahl handelt, lassen Sie den Dezimalteil weg. Ansonsten mit zwei Dezimalstellen formatieren.

DD.
quelle

Antworten:

48

Ich bezweifle das. Das Problem ist, dass 100 niemals 100 ist, wenn es sich um einen Float handelt, normalerweise um 99,9999999999 oder 100,0000001 oder so ähnlich.

Wenn Sie es auf diese Weise formatieren möchten, müssen Sie ein Epsilon definieren, dh einen maximalen Abstand von einer Ganzzahl, und die Ganzzahlformatierung verwenden, wenn der Unterschied kleiner ist, und ansonsten einen Gleitkommawert.

So etwas würde den Trick machen:

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
quelle
8
Kleiner Nitpick: Ein Float kann genau 100 sein, mit dem Bitmuster 0x42c80000.
Karol S
2
Ja, wie von Karol S angegeben, können viele Zahlen durch Floats genau übereinstimmen. Nur nicht ALLE Zahlen. 100 ist eine Zahl, die dargestellt werden kann. Sie sollten nur Zahlen berücksichtigen, die nicht dargestellt werden können.
csga5000
158

Ich würde empfehlen, das Paket java.text zu verwenden:

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

Dies hat den zusätzlichen Vorteil, dass es länderspezifisch ist.

Wenn Sie müssen, kürzen Sie den String, den Sie zurückerhalten, wenn es sich um einen ganzen Dollar handelt:

if (moneyString.endsWith(".00")) {
    int centsIndex = moneyString.lastIndexOf(".00");
    if (centsIndex != -1) {
        moneyString = moneyString.substring(1, centsIndex);
    }
}
Duffymo
quelle
17
Sie sollten niemals ein Doppel verwenden, um Währungen darzustellen. Konvertieren Sie entweder in Longs und verwalten Sie den Dezimalpunkt selbst oder verwenden Sie ihn BigDecimalmit einem Formatierer. joda-money.sourceforge.net sollte eine nette Bibliothek sein, die man verwenden kann, wenn es fertig ist.
Gpampara
5
Ich stimme zu: double! = Geld, aber so wurde die Frage nicht gestellt.
Duffymo
3
Was meinst du damit, wie Währungen funktionieren? Ich kann sagen, dass etwas 1 US-Dollar kostet, nicht 1,00 US-Dollar. Es gibt verschiedene Möglichkeiten, Währungen anzuzeigen (außer der Standardwährung). Bei dieser Frage wird gefragt, wie der Dezimalteil weggelassen werden soll, wenn es sich um eine ganze Zahl handelt.
DD.
1
Es ist ein Rendering-Problem. Fügen Sie die Logik in Ihre Benutzeroberfläche ein, um die Währung als Zeichenfolge zu akzeptieren, und kürzen Sie Dezimalstellen und Cent, wenn es sich um einen exakten Dollar handelt.
Duffymo
2
Einverstanden - deshalb habe ich empfohlen, Locale zu verwenden, als ich dies vor 5,5 Jahren schrieb. "Aber wenn Sie müssen, ..." ist der Schlüsselbegriff.
Duffymo
122
double amount =200.0;
Locale locale = new Locale("en", "US");      
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
System.out.println(currencyFormatter.format(amount));

oder

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

Der beste Weg, um Währung anzuzeigen

Ausgabe

200,00 USD

Wenn Sie kein Zeichen verwenden möchten, verwenden Sie diese Methode

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

200,00

Dies kann auch verwendet werden (mit dem Tausendertrennzeichen)

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

2.000.000,00

Thilina Dharmasena
quelle
Es sieht nicht so aus, als würde "Währung" referenziert oder verwendet, nachdem sie deklariert wurde ... gibt es einen Nebeneffekt von Zeile 3? Oder aus irgendeinem Grund haben Sie es aufgenommen?
Damian
Lesen Sie mehr über [Class Locale] [1] [1]: docs.oracle.com/javase/7/docs/api/java/util/…
Thilina Dharmasena
18

Ich habe nach der Google-Suche keine gute Lösung gefunden. Veröffentlichen Sie einfach meine Lösung, damit andere darauf verweisen können. Verwenden Sie priceToString, um Geld zu formatieren.

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
quelle
Er hat nie gesagt, dass es besser ist. ER hat gerade seine Lösung veröffentlicht, damit andere darauf verweisen können. Zumindest könnte man sagen, ist ein Dank.
Umang Desai
Was ist, wenn ich den Preis im indischen Format anzeigen möchte? Ohne Dezimalstellen. Format -> ##, ##, ###
Bhuvan
Versuchen Sie bei der priceWithDecimal (Double) -Methode, die Maske so "###,###,###.00"zu ändern "###,###,##0.00", dass "0,00"
angezeigt wird,
1
Was wird das umgekehrt, um die formatierte Währung wieder in Double
umzuwandeln
6

Ja. Sie können java.util.formatter verwenden . Sie können eine Formatierungszeichenfolge wie "% 10.2f" verwenden.

dj_segfault
quelle
String.format()ist ein schöner statischer Wrapper dafür. Ich bin mir jedoch nicht sicher, warum Sie '10' verwenden.
Xr.
Da ich keine Anleitung zur Größe der Nummer hatte, entschied ich mich für 10 Ex Recto. Wir wissen nicht, ob dies der Preis für einen Schokoriegel oder ein Auto ist. Ich glaube, Sie können auch einfach "% .2f" ausführen, um die Gesamtgröße unbegrenzt zu lassen.
dj_segfault
DD wollte, dass der Dezimalteil weggelassen wird, wenn der Betrag eine runde Anzahl von Währungseinheiten ist.
jarnbjo
6

Ich benutze dieses (mit StringUtils von commons-lang):

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

Sie müssen sich nur um das Gebietsschema und den entsprechenden zu schneidenden String kümmern.

Dirk Lachowski
quelle
5

Ich denke, dies ist einfach und klar für das Drucken einer Währung:

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

Ausgabe: 12.345,68 USD

Und eine der möglichen Lösungen für die Frage:

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

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

Ausgabe:

100

100.10

Andrey
quelle
Sie haben den Punkt des Beitrags verpasst. Wenn die Zahl eine ganze Zahl ist, möchte ich keine Dezimalstellen anzeigen.
DD.
DD. Es tut mir leid und ich habe die Antwort entsprechend der Frage korrigiert.
Andrey
5

Normalerweise müssen wir das Gegenteil tun. Wenn Ihr json-Geldfeld ein Float ist, kann es 3,1, 3,15 oder nur 3 sein.

In diesem Fall müssen Sie es möglicherweise für eine ordnungsgemäße Anzeige runden (und später eine Maske für ein Eingabefeld verwenden können):

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
quelle
5

dieser beste Weg, das zu tun.

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

Ausgabe:

$123.50

Wenn Sie die Währung ändern möchten,

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

Ausgabe:

123.50
Subhashi
quelle
4

Sie sollten so etwas tun:

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

welche druckt:

100

100,10

Stefan De Boey
quelle
Funktioniert Math.round (d)! = D? Mit schwimmt es oft! = Auch wenn du denkst es ist.
Extraneon
1
Wenn d andernfalls 100.000000000000001 wäre, würde es immer noch als 100 gedruckt
Stefan De Boey
4

Ich weiß, das ist eine alte Frage, aber ...

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
quelle
3
Dies funktioniert nicht, es funktioniert zum Beispiel 100.1 -> "100.1" - siehe stackoverflow.com/questions/5033404/…
davnicwil
4

Sie können einfach so etwas tun und die ganze Zahl und dann die Cent danach eingeben.

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

Ich stimme @duffymo zu, dass Sie die java.text.NumberFormatMethoden für diese Art von Dingen verwenden müssen. Sie können tatsächlich alle Formatierungen nativ ausführen, ohne dass ein String Sie selbst vergleicht:

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

Ein paar Punkte, auf die Sie hinweisen sollten:

  • Das Ganze Math.round(priceAsDouble * 100) % 100 arbeitet nur an den Ungenauigkeiten von Doppel- / Schwimmern. Wenn wir nur prüfen, ob wir auf den Hunderterplatz runden (vielleicht ist dies eine US-Tendenz), sind noch Cent übrig.
  • Der Trick, um die Dezimalstellen zu entfernen, ist die setMaximumFractionDigits()Methode

Was auch immer Ihre Logik für die Bestimmung ist, ob die Dezimalstellen abgeschnitten werden setMaximumFractionDigits()sollen oder nicht, sollte verwendet werden.

xbakesx
quelle
1
Bezüglich Ihres Standpunkts zu *100und %100der US-Voreingenommenheit könnten Sie Math.pow(10, formatter.getMaximumFractionDigits())anstelle einer fest codierten 100Nummer die richtige Nummer für das Gebietsschema verwenden ...
Daiscog
3

Wenn Sie an Währungen arbeiten möchten, müssen Sie die BigDecimal-Klasse verwenden. Das Problem ist, dass es keine Möglichkeit gibt, einige Gleitkommazahlen im Speicher zu speichern (z. B. können Sie 5.3456, aber nicht 5.3455 speichern), was sich auf schlechte Berechnungen auswirken kann.

Es gibt einen schönen Artikel über die Zusammenarbeit mit BigDecimal und Währungen:

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

Adrian Adamczyk
quelle
2
Dies ist für die Frage, die ich gestellt habe, völlig irrelevant.
DD.
3

Format von 1000000,2 bis 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
quelle
2

Dieser Beitrag hat mir wirklich geholfen, endlich das zu bekommen, was ich will. Ich wollte hier nur meinen Code einbringen, um anderen zu helfen. Hier ist mein Code mit einigen Erklärungen.

Der folgende Code:

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

Wird zurückkehren:

 5,-
 5,50

Die eigentliche jeroensFormat () -Methode:

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

Die Methode displayJeroensFormat, die die Methode jeroensFormat () aufruft

    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
    }

Wird die folgende Ausgabe haben:

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

Dieser Code verwendet Ihre aktuelle Währung. In meinem Fall ist das Holland, daher ist die formatierte Zeichenfolge für mich anders als für jemanden in den USA.

  • Holland: 999,999,99
  • US: 999.999,99

Beobachten Sie einfach die letzten 3 Zeichen dieser Zahlen. Mein Code hat eine if-Anweisung, um zu überprüfen, ob die letzten 3 Zeichen gleich ", 00" sind. Um dies in den USA zu verwenden, müssen Sie dies möglicherweise in ".00" ändern, wenn es noch nicht funktioniert.

Jeroen
quelle
2

Ich war verrückt genug, um meine eigene Funktion zu schreiben:

Dadurch wird die Ganzzahl in das Währungsformat konvertiert (kann auch für Dezimalstellen geändert werden):

 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
quelle
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
quelle
1

Dies habe ich getan, indem ich stattdessen eine Ganzzahl verwendet habe, um den Betrag als Cent darzustellen:

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

Das Problem dabei NumberFormat.getCurrencyInstance()ist, dass man manchmal wirklich möchte, dass 20 $ 20 $ sind, es sieht einfach besser aus als 20,00 $.

Wenn jemand mit NumberFormat einen besseren Weg findet, bin ich ganz Ohr.

Viktor Nordling
quelle
1

Für die Leute, die die Währung formatieren möchten, aber nicht möchten, dass sie auf lokal basiert, können wir dies tun:

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
quelle