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

89

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

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

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

DD.
источник

Ответы:

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);
    }
}
Duffymo
источник
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"

dj_segfault
источник
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));
    }
}
Aezur
источник
3
Это не работает, он делает 100,1 -> «100,1», например , - см stackoverflow.com/questions/5033404/...
davnicwil
4

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

String.format("$%,d.%02d",wholeNum,change);
user2645904
источник
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()следует привыкнуть.

xbakesx
источник
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», если это уже не работает.

Jeroen
источник
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);
    }
PRATEEK BHARDWAJ
источник
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...
Хаомин
источник