Формат номера валюты Java


89

Есть ли способ отформатировать десятичную дробь следующим образом:

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

Если это круглое число, опустите десятичную часть. В противном случае форматируйте с двумя десятичными знаками.

Ответы:


48

Я в этом сомневаюсь. Проблема в том, что 100 никогда не бывает 100, если это число с плавающей запятой, обычно это 99.9999999999 или 100.0000001 или что-то в этом роде.

Если вы действительно хотите отформатировать его таким образом, вы должны определить эпсилон, то есть максимальное расстояние от целого числа, и использовать целочисленное форматирование, если разница меньше, и float в противном случае.

Что-то вроде этого поможет:

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

8
Незначительная придирка: число с плавающей запятой может быть ровно 100, с битовой комбинацией 0x42c80000.
Karol S

2
Да, как было заявлено Karol S, многие числа МОГУТ точно соответствовать числам с плавающей запятой. Только не ВСЕ числа. 100 - это одно число, которое может быть представлено, вы должны просто учитывать числа, которых не может быть.
csga5000,

160

Я бы рекомендовал использовать пакет java.text:

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

Это имеет дополнительное преимущество, поскольку оно зависит от локали.

Но, если необходимо, обрежьте строку, которую вы вернете, если это целый доллар:

if (moneyString.endsWith(".00")) {
    int centsIndex = moneyString.lastIndexOf(".00");
    if (centsIndex != -1) {
        moneyString = moneyString.substring(1, centsIndex);
    }
}

17
Никогда не используйте двойные символы для обозначения валют. Либо конвертируйте в длинные числа и управляйте десятичной запятой самостоятельно, либо используйте BigDecimalс форматтером. joda-money.sourceforge.net должна стать хорошей библиотекой для использования, когда она будет готова .
gpampara 04

5
Согласен, re: double! = Деньги, но вопрос был поставлен не так.
duffymo 04

3
Что вы имеете в виду, так работают валюты? Я могу сказать, что что-то стоит 1 доллар, а не 1 доллар .... Существуют разные способы отображения валют (кроме значений по умолчанию), и этот вопрос спрашивает, как опустить десятичную часть, если это целое число.
ДД.

1
Это проблема рендеринга. Поместите логику в свой пользовательский интерфейс, чтобы принимать валюту как строку и усекать десятичную дробь и центы, если это точный доллар.
duffymo

2
Согласен - вот почему я рекомендовал использовать Locale, когда писал это 5,5 лет назад. «Но, если нужно…» - это ключевая фраза.
duffymo

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

или

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

Лучший способ отображения валюты

Выход

200 долларов США

Если вы не хотите использовать знак, используйте этот метод

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

200.00

Это также можно использовать (с разделителем тысяч)

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

2 000 000,00


Не похоже, что "валюта" упоминается или используется после ее объявления ... есть ли побочный эффект строки 3? Или почему-то вы его включили?
Дамиан

Подробнее о [Class Locale] [1] [1]: docs.oracle.com/javase/7/docs/api/java/util/…
Thilina Dharmasena

18

Я не нашел хорошего решения после поиска в Google, просто опубликуйте свое решение для справки другим. используйте priceToString для форматирования денег.

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

Он никогда не говорил, что это лучше. ОН только что опубликовал свое решение, чтобы другие могли ссылаться на него. По крайней мере, можно сказать спасибо.
Уманг Десаи

Что, если я хочу отображать цену в индийском формате. Без десятичных знаков. Формат -> ##, ##, ###
Бхуван

В методе priceWithDecimal (Double) попробуйте изменить маску так, "###,###,###.00"чтобы она "###,###,##0.00"отображала «0,00» при значении «0»
dellasavia

1
что, наоборот, снова конвертирует форматированную валюту в двойную
Вивек Шанкар

6

Да. Вы можете использовать java.util.formatter . Вы можете использовать строку форматирования, например "% 10.2f"


String.format()- хорошая статическая оболочка для этого. Не знаю, почему вы используете «10».
Xr.

Не имея никаких указаний относительно размера числа, я выбрал 10 Ex Recto. Мы не знаем, цена ли это моноблока или автомобиля. Я считаю, что вы также можете просто ввести "% .2f", чтобы оставить неограниченный общий размер.
dj_segfault 04

DD хотел, чтобы десятичная часть была опущена, если сумма является круглым числом денежных единиц.
jarnbjo 04

6

Я использую это (используя StringUtils из commons-lang):

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

Вы должны позаботиться только о локали и соответствующей строке для обрезки.


5

Я считаю, что для печати валюты это просто и понятно:

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

выход: $ 12 345,68

И одно из возможных решений вопроса:

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

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

Выход:

100

100,10


Вы упустили суть поста. Если это целое число, я не хочу отображать десятичные дроби.
ДД.

DD. Прошу прощения, и я исправил ответ по вопросу.
Эндрю

5

Обычно нам нужно сделать обратное, если ваше поле json money является плавающим, это может быть 3,1, 3,15 или просто 3.

В этом случае вам может потребоваться округлить его для правильного отображения (и для возможности использовать маску в поле ввода позже):

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

5

это лучший способ сделать это.

    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»


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

выход:

$123.50

Если вы хотите изменить валюту,

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

выход:

123.50

4

вы должны сделать что-то вроде этого:

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

который печатает:

100

100,10


Будет ли работать Math.round (d)! = D? С поплавками это часто! = Даже если вы думаете, что это так.
extraneon

1
в противном случае, если бы d было 100,000000000000001, то оно все равно было бы напечатано как 100
Стефан Де Бой,

4

Я знаю, что это старый вопрос, но ...

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

3
Это не работает, он делает 100,1 -> «100,1», например , - см stackoverflow.com/questions/5033404/...
davnicwil

4

Вы можете просто сделать что-то вроде этого и передать целое число, а затем центы.

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

4

Я согласен с @duffymo, что вам нужно использовать java.text.NumberFormatметоды для такого рода вещей. На самом деле вы можете выполнять все форматирование изначально в нем, не сравнивая 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);
}

Пара битов, чтобы указать:

  • Целый Math.round(priceAsDouble * 100) % 100 просто работает над неточностями удвоений / поплавков. В основном просто проверяем, округляем ли мы до сотен (возможно, это смещение в США), остались ли центы.
  • Уловка для удаления десятичных знаков - это setMaximumFractionDigits()метод

Какой бы ни была ваша логика для определения, следует ли усекать десятичные дроби, setMaximumFractionDigits()следует привыкнуть.


1
Re вашей точки о *100и %100будучи США предвзятых, вы могли бы использовать Math.pow(10, formatter.getMaximumFractionDigits())вместо жестко , 100чтобы использовать правильный номер для локал ...
daiscog

3

Если вы хотите работать с валютами, вы должны использовать класс BigDecimal. Проблема в том, что нет способа сохранить в памяти некоторые числа с плавающей запятой (например, вы можете хранить 5,3456, но не 5,3455), что может повлиять на неправильные вычисления.

Есть хорошая статья о том, как работать с BigDecimal и валютами:

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


2
Это совершенно не имеет отношения к заданному мною вопросу.
ДД.

3

Формат от 1000000.2 до 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;
}

2

Этот пост действительно помог мне наконец получить то, что я хочу. Поэтому я просто хотел поделиться своим кодом здесь, чтобы помочь другим. Вот мой код с некоторыми пояснениями.

Следующий код:

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

Вернется:

5,-
€ 5,50

Фактический метод jeroensFormat ():

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

Метод displayJeroensFormat, вызывающий метод 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
    }

Будет следующий вывод:

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

В этом коде используется ваша текущая валюта. В моем случае это Голландия, поэтому форматированная строка для меня будет другой, чем для кого-то в США.

  • Голландия: 999.999,99
  • США: 999 999,99

Просто посмотрите на последние 3 символа этих чисел. В моем коде есть оператор if, чтобы проверить, равны ли последние 3 символа «, 00». Чтобы использовать это в США, вам, возможно, придется изменить это на «.00», если это уже не работает.


2

Я был достаточно сумасшедшим, чтобы написать свою собственную функцию:

Это преобразует целое число в формат валюты (также можно изменить десятичные дроби):

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

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

1

Вот что я сделал, вместо этого используя целое число для представления суммы в центах:

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

Проблема в NumberFormat.getCurrencyInstance()том, что иногда вы действительно хотите, чтобы 20 долларов были 20 долларов, это просто выглядит лучше, чем 20 долларов.

Если кто-нибудь найдет лучший способ сделать это, используя NumberFormat, я все уши.


1

Для людей, которые хотят отформатировать валюту, но не хотят, чтобы она была основана на локальной, мы можем сделать следующее:

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...
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.