2

Я нашел ошибку в своем приложении, где мои строки валюты не отображали правильные группировки и десятичные разделители при использовании международного формата. Я извлек код, чтобы попытаться изолировать и продемонстрировать проблему. В приведенном ниже коде я создаю форматировщик США и форматировщик мира. Они оба используют один и тот же шаблон валюты, но форматировщик США использует период как десятичный разделитель, а форматирующий мир использует запятую в качестве разделителя десятичных чисел.Java NumberFormat не учитывает запятую как разделитель десятичных чисел

Когда я прошу форматировать World рассказать мне, что его разделители, он сообщает о них правильно. Однако, когда у меня он генерирует строку для моего значения, она не делает это должным образом. Это странно использует период как для группировки И десятичного разделителя.

public static void main(String[] args) throws Exception { 

    String currencyFormat = "¤#,##0.00;-¤#,##0.00"; 
    NumberFormat currencyUSA = NumberFormat.getCurrencyInstance(); 
    DecimalFormat decimalCurrencyUSA = (DecimalFormat)currencyUSA; 
    decimalCurrencyUSA.applyPattern(currencyFormat); 

    NumberFormat currencyWorld = NumberFormat.getCurrencyInstance(); 
    DecimalFormat decimalCurrencyWorld = (DecimalFormat)currencyWorld; 
    decimalCurrencyWorld.applyPattern(currencyFormat); 

    DecimalFormatSymbols decimalFormatSymbols = decimalCurrencyWorld.getDecimalFormatSymbols(); 
    //DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.GERMAN); 

    System.out.println(String.format("Original grouping: %c decimal: %c", decimalFormatSymbols.getGroupingSeparator(), decimalFormatSymbols.getDecimalSeparator())); 
    decimalFormatSymbols.setDecimalSeparator(','); 
    decimalFormatSymbols.setGroupingSeparator('.'); 
    decimalCurrencyWorld.setDecimalFormatSymbols(decimalFormatSymbols); 
    System.out.println(String.format(" After grouping: %c decimal: %c", decimalFormatSymbols.getGroupingSeparator(), decimalFormatSymbols.getDecimalSeparator())); 

    String moneyUSA = currencyUSA.format(1500.75); 
    String moneyWorld = currencyWorld.format(1500.75); 

    DecimalFormatSymbols decimalFormatSymbols2 = decimalCurrencyWorld.getDecimalFormatSymbols(); 
    System.out.println(String.format(" Real grouping: %c decimal: %c", decimalFormatSymbols2.getGroupingSeparator(), decimalFormatSymbols2.getDecimalSeparator())); 

    System.out.println(String.format(" USA String: %s", moneyUSA)); 
    System.out.println(String.format("World String: %s", moneyWorld)); 

    Number numberUSA = currencyUSA.parse(moneyUSA); 
    Number numberWorld = currencyWorld.parse(moneyWorld); 

    System.out.println(String.format(" USA Number: %f", numberUSA)); 
    System.out.println(String.format("World Number: %f", numberWorld)); 

} 

Когда я запускаю приведенный выше код (на моем Mac OS X 10.9, Eclipse Indigo, Java 1.6), выход:

Original grouping: , decimal: . 
    After grouping: . decimal: , 
    Real grouping: . decimal: , 
    USA String: $1,500.75 
World String: $1.500.75 
    USA Number: 1500.750000 
World Number: 1.500000 

Значение валюты World должна быть $ 1.500,75 однако это использовал период в обоих местах.

EDIT:

мне нужно контролировать разделители специально. Я могу уважать локаль пользователя, когда дело доходит до символа валюты, но из-за требований этого приложения мне нужно предоставить пользователю возможность менять период/запятую, когда дело доходит до разделителей. Я не могу просто полагаться на Locale, чтобы управлять этими вещами.

Проблема в том, что я четко определяю эти значения в своих фортанах, и они не соблюдаются.

EDIT 2: я добавил код, чтобы проанализировать ранее сгенерированную денежную строку, чтобы увидеть, соблюдаются ли разделители десятичных разрядов для синтаксического анализа, но не для форматирования. Похоже, что во время разбора период все еще рассматривается как десятичный разделитель, так как World Number выдается как 1.5 вместо 1500.75.

ответ

2

От Customizing Formats

¤ знака валюты; заменен символом валюты; если в два раза заменить символ международной валюты; если он присутствует в образце, денежный десятичного разделителя используется вместо десятичного разделителя

Итак:

decimalFormatSymbols.setMonetaryDecimalSeparator(','); 

будет это делать.

3

Если вы изменяете

DecimalFormatSymbols decimalFormatSymbols = decimalCurrencyWorld.getDecimalFormatSymbols();

в

DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.GERMAN);

(или какой-либо другой Locale), вы обнаружите, что сепараторы работают должным образом.

decimalFormatSymbols.setDecimalSeparator(',');, по-видимому, не меняет формат (хотя setGroupingSeparator() делает, как вы обнаружили).

+0

Да, это сработает.1+ –

+0

Я не могу установить Locale явно так, как это для этого приложения. Пользовательский язык по умолчанию соблюден для символа валюты, но я должен контролировать разделители десятичных и групповых значений напрямую. Финансовый калькулятор HP 10bii для моего приложения mimic, в котором есть кнопка, которая меняет период с запятой, поэтому мне нужно имитировать эту функциональность. –

+0

Я удивлен, что decimalFormatSymbols.setDecimalSeparator (','); не работает так, как мы ожидали бы, тогда как setGroupingSeparator действительно работает. Либо это ошибка на Java (которая, как я считаю, маловероятна, но вы никогда не знаете), или здесь есть предположение, что мы отсутствуем. –

Смежные вопросы