Как использовать Java DecimalFormat для умного форматирования валюты?

Я хотел бы использовать Java DecimalFormat для форматирования двойников следующим образом:

#1 - 100 -> $100
#2 - 100.5 -> $100.50
#3 - 100.41 -> $100.41

Лучшее, что я могу придумать до сих пор, это:

new DecimalFormat("'$'0.##");

Но это не работает для случая № 2 и вместо этого выводит «100,5 долларов США».

Редактировать:

Многие из этих ответов рассматривают только случаи № 2 и № 3 и не понимают, что их решение приведет к тому, что № 1 отформатирует 100 как «100 долларов США», а не просто «100 долларов США».


person Peter    schedule 17.02.2011    source источник
comment
Кстати, использование двойных чисел для представления денежных значений — плохая идея: stackoverflow.com/q/3730019/56285   -  person Jonik    schedule 17.02.2011
comment
Кстати, большинство цен представлены в виде double (или int с фиксированной точностью) в банках.   -  person Peter Lawrey    schedule 17.02.2011


Ответы (10)


Нужно ли использовать DecimalFormat?

Если нет, похоже, должно работать следующее:

String currencyString = NumberFormat.getCurrencyInstance().format(currencyNumber);
//Handle the weird exception of formatting whole dollar amounts with no decimal
currencyString = currencyString.replaceAll("\\.00", "");
person Bradley Swain    schedule 17.02.2011
comment
'currencyString.replaceAll(regexp, String)' в этом случае неэффективен. 'currencyString = currencyString.replace( .00, );' намного эффективнее. replaceAll требует компиляции шаблона, создания сопоставления и т. д. Это может быть довольно дорогостоящим, особенно если код выполняется в цикле отображения на мобильных устройствах с ограниченными ресурсами (Android). - person Frank Harper; 02.08.2013
comment
Стоит отметить, что NumberFormat.getCurrencyInstance() будет форматироваться только с помощью $, если для вашего Locale установлено значение US. Чтобы явно указать валюту, вы можете передать Locale - например, NumberFormat.getCurrencyInstance(Locale.US) здесь - person davnicwil; 16.02.2014

Используйте числовой формат:

NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
double doublePayment = 100.13;
String s = n.format(doublePayment);
System.out.println(s);

Кроме того, не используйте двойные числа для представления точных значений. Если вы используете значения валюты в чем-то вроде метода Монте-Карло (где значения в любом случае не точны), предпочтительнее использовать double.

См. также: Написание программ на Java для расчета и форматирования валюты

person Alexandra Dumas    schedule 17.02.2011
comment
это не работает для случая № 1 ... он форматирует 100 как 100 долларов вместо 100 долларов. - person Peter; 17.02.2011
comment
Да, это не распространяется на случай setMinimumFractionDigits(0). - person Will Sargent; 22.03.2012

Пытаться

new DecimalFormat("'$'0.00");

Редактировать:

Я пытался

DecimalFormat d = new DecimalFormat("'$'0.00");

        System.out.println(d.format(100));
        System.out.println(d.format(100.5));
        System.out.println(d.format(100.41));

и получил

$100.00
$100.50
$100.41
person Bala R    schedule 17.02.2011
comment
это не работает для случая № 1 ... он форматирует 100 как 100 долларов вместо 100 долларов. - person Peter; 17.02.2011
comment
DecimalFormat(0.00) работает для разбора в двойное число. Спасибо за этот простой ответ - person Haider Malik; 17.05.2020

Попробуйте использовать

DecimalFormat.setMinimumFractionDigits(2);
DecimalFormat.setMaximumFractionDigits(2);
person Rafael T    schedule 17.02.2011
comment
оно делает! codepublic class Testing { /** * @param args */ public static void main(String[] args) { double d = 100.5; DecimalFormat df = новый DecimalFormat('$'0.##); df.setMaximumFractionDigits (2); df.setMinimumFractionDigits(2); Строковая валюта = df.format(d); System.out.println(валюта); } } code - person Rafael T; 17.02.2011
comment
@ Питер, ты имел в виду случай №1? Вот где это, похоже, не работает (Java 1.6.0_22 на Mac), производя 100 долларов вместо 100 долларов, чего хотел OP. - person Jonik; 17.02.2011
comment
@Jonik да, точно, извините за опечатку. Я в основном определил, что это невозможно с помощью DecimalFormat, и перешел на другие средства для решения этой проблемы. Спасибо! - person Peter; 17.02.2011
comment
Хорошо. Вы правы. Вы можете попытаться «взломать» его для случая № 1, если вы проверите codeif(currency.substring(currency.indexOf(.)).equals(00)) { currency = currency.substring(0,currency.indexOf( .)) } code - person Rafael T; 17.02.2011

Вы можете проверить "число целое или нет" и выбрать нужный формат числа.

public class test {

  public static void main(String[] args){
    System.out.println(function(100d));
    System.out.println(function(100.5d));
    System.out.println(function(100.42d));
  }

  public static String function(Double doubleValue){
    boolean isWholeNumber=(doubleValue == Math.round(doubleValue));
    DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(Locale.GERMAN);
    formatSymbols.setDecimalSeparator('.');

    String pattern= isWholeNumber ? "#.##" : "#.00";    
    DecimalFormat df = new DecimalFormat(pattern, formatSymbols);
    return df.format(doubleValue);
  }
}

даст именно то, что вы хотите:

100
100.50
100.42
person ashakirov    schedule 23.11.2012

Вы можете использовать следующий формат:

DecimalFormat dformat = новый DecimalFormat("$#.##");

person mizanurahma    schedule 12.05.2014

Я знаю, что слишком поздно. Однако у меня сработало следующее:

DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.UK);
new DecimalFormat("\u00A4#######0.00",otherSymbols).format(totalSale);

 \u00A4 : acts as a placeholder for currency symbol
 #######0.00 : acts as a placeholder pattern for actual number with 2 decimal 
 places precision.   

Надеюсь, это поможет тем, кто читает это в будущем :)

person Shailesh Vaishampayan    schedule 14.01.2017

Вы можете попробовать использовать два разных объекта DecimalFormat в зависимости от следующего условия:

double d=100;
double d2=100.5;
double d3=100.41;

DecimalFormat df=new DecimalFormat("'$'0.00");

if(d%1==0){ // this is to check a whole number
    DecimalFormat df2=new DecimalFormat("'$'");
    System.out.println(df2.format(d));
}

System.out.println(df.format(d2));
System.out.println(df.format(d3));

Output:-
$100
$100.50
$100.41
person Sai Gattu    schedule 19.06.2017

Для этого вы можете использовать Java Money API. (хотя это не использует DecialFormat)

long amountInCents = ...;
double amountInEuro = amountInCents / 100.00;

String customPattern; 
if (minimumOrderValueInCents % 100 == 0) {
    customPattern = "# ¤";
} else {
    customPattern = "#.## ¤";
}

Money minDeliveryAmount = Money.of(amountInEuro, "EUR");
MonetaryAmountFormat formatter = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.of(Locale.GERMANY)
            .set(CurrencyStyle.SYMBOL)
            .set("pattern", customPattern)
            .build());

System.out.println(minDeliveryAmount);
person Sebastian Thees    schedule 13.05.2019

printf тоже работает.

Пример:

удвоить любое число = 100; printf("Значение %4.2f ", anyNumber);

Вывод:

Стоимость 100,00

4.2 означает, что число должно иметь две цифры после запятой. 4 определяет, сколько цифр справа от десятичной дроби.

person Casper    schedule 08.03.2013
comment
Это не обрабатывает добавление запятых для больших чисел, но работает, учитывая примеры. - person ingyhere; 16.12.2013