Как вы форматируете дробный процент с java.text.MessageFormat - PullRequest
33 голосов
/ 30 марта 2009

Мои проценты усекаются функцией java.text.MessageFormat по умолчанию. Как отформатировать проценты без потери точности?

Пример:

String expectedResult = "12.5%";
double fraction = 0.125;

String actualResult = MessageFormat.format("{0,number,percent}", fraction);
assert expectedResult.equals(actualResult) : actualResult +" should be formatted as "+expectedResult;

Ответы [ 6 ]

51 голосов
/ 30 марта 2009

Я думаю, что правильный способ сделать это следующий:

NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(1);
String result = percentFormat.format(0.125);

Также учитывает интернализацию. Например на моей машине с венгерским языком я получил "12,5%", как и ожидалось Инициализация процентов формата как NumberFormat.getPercentInstance(Locale.US) дает «12,5%», конечно.

51 голосов
/ 30 марта 2009

выглядит так:

String actualResult = MessageFormat.format("{0,number,#.##%}", fraction);

... работает.

РЕДАКТИРОВАТЬ: Чтобы увидеть, как интерпретируются # и%, см. Javadoc java.text.DecimalFormat.

РЕДАКТИРОВАТЬ 2: И, да, это безопасно для интернационализации. Точка в строке формата интерпретируется как десятичный разделитель, а не как жестко закодированная точка. : -)

6 голосов
/ 30 марта 2009

Как насчет

DecimalFormat f = new DecimalFormat( "###.#" );
System.out.println( f.format( 12.5 ) );

Формат char '#' не печатает 0 как отсутствующий. Итак, 12,5 -> «12,5», 12,0 -> «12», а не «12,0». Конечно, вы можете настроить свой форматер, например, с помощью "###, ###. ##", место для сотен будет отображаться только если вам нужна точность.

3 голосов
/ 30 марта 2009

Вы понимаете, что "expectedResult == actualResult" всегда будет ложным, верно?

В любом случае, лучшее решение, которое я могу найти, - это явно установить форматтер. Это код, который я тестировал:

String expectedResult = "12.5%";
double fraction = 0.125;
MessageFormat fmt = new MessageFormat("{0,number,percent}");
NumberFormat nbFmt = NumberFormat.getPercentInstance();
nbFmt.setMaximumFractionDigits(1); // or 2, or however many you need
fmt.setFormatByArgumentIndex(0, nbFmt);
String actualResult = fmt.format(new Object[] {fraction});
assert expectedResult.equals(actualResult) : actualResult +" is getting rounded off";
2 голосов
/ 18 марта 2015

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

/**
 * Formats the given Number as percentage with necessary precision.
 * This serves as a workaround for {@link NumberFormat#getPercentInstance()} which does not renders fractional
 * digits.
 *
 * @param number
 * @param locale
 *
 * @return
 */
public static String formatPercentFraction(final Number number, final Locale locale)
{
    if (number == null)
        return null;

    // get string representation with dot
    final String strNumber = NumberFormat.getNumberInstance(Locale.US).format(number.doubleValue());
    // create exact BigDecimal and convert to get scale
    final BigDecimal dNumber = new BigDecimal(strNumber).multiply(new BigDecimal(100));

    final NumberFormat percentScaleFormat = NumberFormat.getPercentInstance(locale);
    percentScaleFormat.setMaximumFractionDigits(Math.max(0, dNumber.scale()));

    // convert back for locale percent formatter
    return percentScaleFormat.format(dNumber.multiply(new BigDecimal(0.01)));
}
2 голосов
/ 20 апреля 2011

Если интернационализация вызывает беспокойство:

// get locale from somewhere. default is usually a bad idea, especially
// if running in a app server
Locale locale = Locale.getDefault();
NumberFormat fmt = NumberFormat.getPercentInstance(locale);
// the question requires 1 digit for fractional part
// therefore set both, minimum and maximum digit count
fmt.setMinimumFractionDigits(1);
fmt.setMaximumFractionDigits(1);
// set grouping, if you expect large values
// notabene: not all languages use 3 digits per group
fmt.setGroupingUsed(true);
// output the example of the original question
System.out.println(fmt.format(0.125));

Форматировщик числа процентов добавляет пробел и знак процента к выходным данным в известных мне локалях. Я не знаю, находится ли знак процента перед цифрами в других локалях (например, справа налево).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...