我希望能够在格式字符串中给定多个小数位的情况下将字符串转换为 Double 。所以“###,## 0.000”应该给我一个 Double 到3位小数。
编辑 - 为发生的事情添加了更多信息
用户在UI中输入值 - 输入到String中。规则是此值限制为3位小数。底层代码将值存储在数据库中,然后在计算中使用。因此,尾随小数位将导致计算略微超出预期。
我有以下代码:
try {
// output current locale we are running under (this happens to be "nl_BE")
System.out.println( "Current Locale is " + Locale.getDefault().toString() );
// number in Central European Format with a format string specified in UK format
String numberCE = "1,234567"; // 1.234567
String formatUK = "###,##0.000";
// do the format
DecimalFormat formatterUK = new DecimalFormat( formatUK );
Double valCEWithUKFormat = formatterUK.parse( numberCE ).doubleValue();
// I want the number to DPs in the format string!!!
System.out.println( "CE Value " + numberCE + " in UK format (" + formatUK + ") is "
+ valCEWithUKFormat );
} catch( ParseException ex ) {
System.out.println("Cannot parse number");
}
}
DecimalFormat似乎忽略了格式字符串,并将完整的字符串作为 Double 1.234567。
在解析时,DecimalFormat可以强制使用格式字符串吗?我错过了什么吗?
干杯,
Andez
答案 0 :(得分:18)
DecimalFormat用于两个不同的目的:解析输入和格式输出。如果要同时执行这两项操作,则必须使用格式对象两次。
如果要获取该值并格式化输出,限制有效位数,则需要再次使用格式对象。这次它使用您的格式规则从数值创建输出字符串:
String output = formatterUK.format(valCEWithUKFormat.doubleValue() );
这将为您提供1,235
您似乎希望此数值以1.235格式显示。为此,您应该使用特定的区域设置格式化输出(如果您使用不同的格式)。
但,我建议采用不同方式处理此问题:
String text = "1,234567";
NumberFormat nf_in = NumberFormat.getNumberInstance(Locale.GERMANY);
double val = nf_in.parse(text).doubleValue();
NumberFormat nf_out = NumberFormat.getNumberInstance(Locale.UK);
nf_out.setMaximumFractionDigits(3);
String output = nf_out.format(val);
一些注意事项:
答案 1 :(得分:4)
接受你所说的我稍微修改了我的代码以涵盖不同的语言环境。关键是将本地化格式的值字符串转换为基于格式字符串舍入的Double。
格式字符串始终是基于英国的格式,小数分隔符指定为“。”和千名分隔符指定为“,”。
我正在使用DecimalFormat来初始化基于指定语言环境的本地化格式。这样可以正确地给出一个Double等价的字符串。然后我使用BigDecimal来处理舍入。我可以从DecimalFormat实例中获取小数位数,并在BigDecimal上调用setScale来执行舍入。
初始代码结构已经过修改,允许您查看在不同语言环境下发生的情况,感谢@ RD01,以了解其他语言环境的重要性。
我现在的代码如下:
private void runTests3() {
// output current locale we are running under
System.out.println( "Current Locale is " + Locale.getDefault().toString() );
// number in Central European Format with a format string specified in UK format
String numbersInEuropeanFormatString[] = new String[] { "1.000,234567", "1,2345678", "1.222.333,234567" };
String formatUK = "###,##0.0000";
// output numbers using the german locale
System.out.println("Output numbers using the German locale\n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble(num, formatUK, Locale.GERMAN);
}
// output numbers using the UK locale.
// this should return unexpected results as the number is in European format
System.out.println("Output numbers using the UK locale\n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble(num, formatUK, Locale.UK);
}
// output numbers using new DecimalFormat( formatUK ) - no locale specified
System.out.println("\n\nOutput numbers using new DecimalFormat( " + formatUK + " )\n");
for(String num : numbersInEuropeanFormatString ) {
formatNumberAsDouble( num, formatUK, null);
}
}
private void formatNumberAsDouble(String value, String format, Locale locale) {
NumberFormat formatter;
int decimalPlaces;
// create the formatter based on the specified locale
if( locale != null ) {
formatter = NumberFormat.getNumberInstance(locale);
// creating the above number format does not take in the format string
// so create a new one that we won't use at all just to get the
// decimal places in it
decimalPlaces = (new DecimalFormat(format)).getMaximumFractionDigits();
} else {
formatter = new DecimalFormat( format );
decimalPlaces = formatter.getMaximumFractionDigits();
}
// get the result as number
Double result = null;
try {
result = formatter.parse( value ).doubleValue();
} catch( ParseException ex ) {
// not bothered at minute
}
// round the Double to the precision specified in the format string
BigDecimal bd = new BigDecimal(result );
Double roundedValue = bd.setScale( decimalPlaces, RoundingMode.HALF_UP ).doubleValue();
// output summary
System.out.println("\tValue = " + value);
System.out.println( locale == null ? "\tLocale not specified" : "\tLocale = " + locale.toString());
System.out.println( format == null || format.length() == 0 ? "\tFormat = Not specified" : "\tFormat = " + format);
System.out.println("\tResult (Double) = " + result);
System.out.println("\tRounded Result (Double) (" + decimalPlaces + "dp) = " + roundedValue);
System.out.println("");
}
这会产生以下输出:
Current Locale is nl_BE
Output numbers using the German locale
Value = 1.000,234567
Locale = de
Format = ###,##0.0000
Result (Double) = 1000.234567
Rounded Result (Double) (4dp) = 1000.2346
Value = 1,2345678
Locale = de
Format = ###,##0.0000
Result (Double) = 1.2345678
Rounded Result (Double) (4dp) = 1.2346
Value = 1.222.333,234567
Locale = de
Format = ###,##0.0000
Result (Double) = 1222333.234567
Rounded Result (Double) (4dp) = 1222333.2346
Output numbers using the UK locale
Value = 1.000,234567
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.0
Rounded Result (Double) (4dp) = 1.0
Value = 1,2345678
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.2345678E7
Rounded Result (Double) (4dp) = 1.2345678E7
Value = 1.222.333,234567
Locale = en_GB
Format = ###,##0.0000
Result (Double) = 1.222
Rounded Result (Double) (4dp) = 1.222
Output numbers using new DecimalFormat( ###,##0.0000 )
Value = 1.000,234567
Locale not specified
Format = ###,##0.0000
Result (Double) = 1000.234567
Rounded Result (Double) (4dp) = 1000.2346
Value = 1,2345678
Locale not specified
Format = ###,##0.0000
Result (Double) = 1.2345678
Rounded Result (Double) (4dp) = 1.2346
Value = 1.222.333,234567
Locale not specified
Format = ###,##0.0000
Result (Double) = 1222333.234567
Rounded Result (Double) (4dp) = 1222333.2346
答案 2 :(得分:1)
DecimalFormat中小数位的限制实际上是在format()
方法中使用,并且在parse()
方法中没有太大作用。
为了得到你想要的东西,你需要这个:
try {
// output current locale we are running under (this happens to be "nl_BE")
System.out.println("Current Locale is " + Locale.getDefault().toString());
// number in Central European Format with a format string specified in UK format
String numberCE = "1,234567"; // 1.234567
String formatUK = "###,##0.000";
// do the format
DecimalFormat formatterUK = new DecimalFormat(formatUK);
Double valCEWithUKFormat = formatterUK.parse(numberCE).doubleValue();
// first convert to UK format string
String numberUK = formatterUK.format(valCEWithUKFormat);
// now parse that string to a double
valCEWithUKFormat = formatterUK.parse(numberUK).doubleValue();
// I want the number to DPs in the format string!!!
System.out.println("CE Value " + numberCE + " in UK format (" + formatUK + ") is " + valCEWithUKFormat);
} catch (ParseException ex) {
System.out.println("Cannot parse number");
}
首先需要将数字作为英国格式字符串,然后使用英国格式化程序解析该数字。这将为您提供您正在寻找的结果。注意,这会将数字四舍五入到小数点后3位,而不是截断。
顺便说一句,我对您的英国格式化程序能够解析CE格式编号感到有些惊讶。你真的应该使用CE格式解析器解析原始数字。
答案 3 :(得分:0)
当然可以。试试这个:
String in = "1,234567";
System.out.println(NumberFormat.getNumberFormat(new Locale("fr", "FR")).parse(in));
System.out.println(NumberFormat.getNumberFormat(new Locale("en", "GB")).parse(in));
显然,它们会产生不同的输出,第一个读数1.234567
和第二个1234567
。也许你的模式出了问题?无论如何,最后一行将是获得UK
标准格式的首选方式。