如何使用java.text.MessageFormat设置分数百分比的格式
我的百分比被默认的java.text.MessageFormat函数截断,如何在不损失精度的情况下格式化百分比 例如:如何使用java.text.MessageFormat设置分数百分比的格式,java,text,localization,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) : actualResu
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;
怎么样
DecimalFormat f = new DecimalFormat( "###.#" );
System.out.println( f.format( 12.5 ) );
格式字符“#”不会将0打印为不存在。所以12.5->“12.5”,12.0->“12”,而不是“12.0”。当然,您可以使用例如“#####,####,####”来设置格式化程序,第一百位仅在您需要精度时才会显示。您确实意识到“expectedResult==actualResult”
将始终为false,对吗
无论如何,我能找到的最佳解决方案是显式设置格式化程序。这是我测试的代码:
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";
看起来像这样:
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%”。将percentFormat初始化为
NumberFormat.getPercentInstance(Locale.US)
当然会给出“12.5%”。如果需要国际化:
// 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));
百分比数字格式化程序在我知道的区域设置的输出中附加一个空格和百分号。我不知道百分比符号的位置是否在其他区域设置的数字之前(例如从右到左的区域设置)。我的解决方案呈现给定数字上设置的小数位数。使用多种基本类型和
数字类型进行单元测试
/**
* 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)));
}
然而,国际化可能并不安全。我不确定。本地化程序总是有破坏某些格式字符串的危险,但除此之外,我无法考虑任何其他问题。。。