如何使用java.text.MessageFormat格式化小数百分比

时间:2009-03-30 17:45:03

标签: java text localization

我的百分比被默认的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 个答案:

答案 0 :(得分:51)

看起来像这样:

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

......正在发挥作用。

编辑:要了解#和%的解释,请参阅java.text.DecimalFormat的javadoc。

编辑2:是的,国际化是安全的。格式字符串中的点被解释为小数点分隔符,而不是硬编码点。 : - )

答案 1 :(得分:51)

我认为正确的做法如下:

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

它还考虑了内部化。例如,在我的匈牙利语语言环境的机器上,我得到了“12,5%”。将percentFormat初始化为NumberFormat.getPercentInstance(Locale.US)当然会给出“12.5%”。

答案 2 :(得分:6)

怎么样

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

格式字符'#'不会打印0作为缺席。所以12.5 - >“12.5”,12.0 - > “12”,而不是“12.0”。您当然可以设置格式化程序,例如“###,###。##”,只有你需要精确度才会显示hundreths地方。

答案 3 :(得分:3)

你确实意识到"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";

答案 4 :(得分:2)

如果国际化是一个问题:

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

百分比格式化程序在我知道的语言环境中将空格和百分号附加到输出。我不知道,百分号的位置是否在其他语言环境中的数字之前(例如从右到左的语言环境)。

答案 5 :(得分:2)

我的解决方案呈现与给定数字上设置的比例一样多的小数位数。单元测试了许多原始和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)));
}