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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/698261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:28:24  来源:igfitidea点击:

How do you format a fractional percentage with java.text.MessageFormat

javatextlocalization

提问by Lorin

My percentages get truncated by the default java.text.MessageFormat function, how do you format a percentage without losing precision?

我的百分比被默认的 java.text.MessageFormat 函数截断,你如何在不丢失精度的情况下格式化百分比?

Example:

例子:

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;

采纳答案by david a.

Looks like this:

看起来像这样:

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

... is working.

... 正在工作。

EDIT: To see how are the #'s and %'s interpreted, see the javadoc of java.text.DecimalFormat.

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

EDIT 2: And, yes, it is safe for internationalization. The dot in format string is interpreted as a decimal separator, not as a hardcoded dot. :-)

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

回答by Steve B.

How about

怎么样

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

The format char '#' does not print a 0 as absent. So 12.5 ->"12.5", 12.0 -> "12", not "12.0". You could of course set up your formatter with e.g. "###,###.##", the hundreths place will only show up if you need the precision.

格式字符 '#' 不会将 0 打印为不存在。所以 12.5 ->"12.5", 12.0 -> "12",而不是 "12.0"。您当然可以使用例如“###,###.##”来设置格式化程序,只有在您需要精度时才会显示百位。

回答by Michael Myers

You do realize that "expectedResult == actualResult"will always be false, right?

你确实意识到那"expectedResult == actualResult"永远是假的,对吧?

Anyway, the best solution I can find is to set the formatter explicitly. This is the code I tested:

无论如何,我能找到的最佳解决方案是明确设置格式化程序。这是我测试的代码:

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";

回答by Chei

I think the proper way to do it is the following:

我认为正确的方法如下:

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

It also takes internalization into account. For example on my machine with hungarian locale I got "12,5%" as expected. Initializing percentFormat as NumberFormat.getPercentInstance(Locale.US)gives "12.5%" of course.

它还考虑了内化。例如,在我使用匈牙利语环境的机器上,我得到了预期的“12.5%”。当然,将percentFormat 初始化为NumberFormat.getPercentInstance(Locale.US)“12.5%”。

回答by rhjoerg

If internationalization is a concern:

如果国际化是一个问题:

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

The percent number formatter appends a space and the percent sign to the output in the locales I know. I don't know, whether the position of the percent sign is before the digits in other locales (right-to-left locales for instance).

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

回答by djmj

My solution renders as many fractional digits as scale was set on given Number. Unit tested with many primitive and Numbertypes.

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