簡體   English   中英

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

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

我的百分比被默認的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;

看起來像這樣:

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

... 工作中。

編輯:要查看#和%的解釋,請參閱java.text.DecimalFormat的javadoc。

編輯2:是的,國際化是安全的。 格式字符串中的點被解釋為小數點分隔符,而不是硬編碼點。 :-)

我認為正確的方法如下:

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

它還考慮了內部化。 例如,在我的匈牙利語語言環境的機器上,我得到了“12,5%”。 NumberFormat.getPercentInstance(Locale.US)初始化為NumberFormat.getPercentInstance(Locale.US)當然會給出“12.5%”。

怎么樣

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

char'#'格式不打印0表示不存在。 所以12.5 - >“12.5”,12.0 - >“12”,而不是“12.0”。 您當然可以使用例如“###,###。##”設置格式化程序,只有在需要精度時才會顯示hundreths位置。

你確實意識到"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";

我的解決方案呈現與給定數字上設置的比例一樣多的小數位數。 單元測試了許多原始和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)));
}

如果國際化是一個問題:

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

百分號格式化程序在我知道的語言環境中將空格和百分號附加到輸出。 我不知道,百分號的位置是否在其他語言環境中的數字之前(例如從右到左的語言環境)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM