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


89

Чи є спосіб відформатувати десятковий знак таким чином:

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

Якщо це кругле число, опустіть десяткову частину. В іншому випадку форматуйте з двома знаками після коми.

Відповіді:


48

Я сумніваюся. Проблема полягає в тому, що 100 ніколи не є 100, якщо це поплавок, це зазвичай 99,9999999999 або 100,0000001 або щось подібне.

Якщо ви хочете відформатувати його таким чином, вам потрібно визначити епсилон, тобто максимальну відстань від цілого числа, і використовувати цілочисельне форматування, якщо різниця менша, а в іншому випадку - з плаваючою точкою.

Щось подібне зробить фокус:

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
Так, як заявила Кароль 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
Ніколи не слід використовувати двійник для представлення валют. Або перетворіть у long і керуйте десятковою точкою самостійно, або використовуйте BigDecimalза допомогою форматування. joda-money.sourceforge.net має бути приємною бібліотекою для використання, коли це буде зроблено.
gpampara

5
Я згоден re: double! = Гроші, але не так ставилося питання.
duffymo

3
Що ви маєте на увазі, саме так працюють валюти? Я можу сказати, що дещо коштує 1 долар, а не 1,00 доларів .... Існують різні способи відображення валют (крім типових), і це питання задає питання, як опустити десяткову частину, якщо це ціле число.
ДД.

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,00 дол

Якщо ви не хочете використовувати знак, використовуйте цей метод

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? Або чомусь ви його включили?
Даміан,

Докладніше про [Locale класу] [1] [1]: docs.oracle.com/javase/7/docs/api/java/util/…
Тхіліна Дхармасена,

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
що буде навпаки, щоб знову перетворити відформатовану валюту на Double
Вівек Шанкар

6

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


String.format()це хороша статична обгортка для цього. Не впевнений, чому ви використовуєте "10".
Xr.

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

ДД хотів, щоб десяткова частина була опущена, якщо сума є округлою кількістю одиниць валюти.
jarnbjo

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


Ви пропустили суть допису. Якщо число - це ціле число, я не хочу відображати десяткові крапки.
ДД.

ДД. Вибачте, і я виправив відповідь відповідно до запитання.
Ендрю

5

Зазвичай нам потрібно буде зробити зворотне, якщо ваше грошове поле json є плаваючим, воно може мати значення 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? З поплавками це часто! = Навіть якщо ви думаєте, що так.
екстранеон

1
в іншому випадку, якщо d буде 100,000000000000001, то він все одно буде надрукований як 100
Stefan De Boey

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методи для такого роду речей. Ви можете фактично виконати все форматування в ньому, не виконуючи жодного порівняння рядка:

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,00 доларів.

Якщо хтось знайде кращий спосіб зробити це, використовуючи 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.