以下是Exception的结果:
String p="1,234";
Double d=Double.valueOf(p);
System.out.println(d);
与p = p.replaceAll(",",".");相比,有没有更好的方法解析"1,234"以获取1.234?
以我的经验,如您所建议,replaceAll()是执行此操作的最佳方法。它不依赖于当前语言环境,它很简单,并且可以正常工作。
@JoonasPulakka,仅当当前默认语言环境使用点作为小数点分隔符时,您的建议才有效。对 ?
@Marco Altieri:replaceAll(",",".")用点替换所有逗号。如果没有逗号,则不执行任何操作。 Double.valueOf()(仅)适用于使用点作为小数点分隔符的字符串。当前的默认语言环境不会影响此处的任何内容。 docs.oracle.com/javase/8/docs/api/java/lang/
replaceAll(",",".")的唯一问题是,它只有在有一个逗号的情况下才起作用:即:1,234,567将抛出java.lang.NumberFormatException: multiple points。正向查找的正则表达式足以满足p.replaceAll(",(?=[0-9]+,)","").replaceAll(",",".")的需求,网址为:regular-expressions.info/lookaround.html
没有问题。 NumberFormatException是好的。您怎么知道哪个逗号是正确的?格式错误,您所能做的就是向用户显示比异常情况更好的可读性消息。
@TheincredibleJan不,格式没有错误。一些语言环境使用逗号作为千位分隔符,因此您可以在数字中使用多个逗号,并且从技术上讲,它仍然是有效的输入。
使用java.text.NumberFormat:
NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
Number number = format.parse("1,234");
double d = number.doubleValue();
仅当当前的默认语言环境恰好使用逗号作为小数点分隔符时,此方法才有效。
为了进一步解决问题,某些语言环境使用逗号作为千位分隔符,在这种情况下," 1,234"将解析为1234.0而不是抛出错误。
一些欧洲语言环境(例如FRANCE,德国和意大利)使用逗号作为小数点分隔符,因此您可以显式使用它们,而不必依赖默认值。
NumberFormat的问题在于它将静默忽略无效字符。因此,如果您尝试解析" 1,23abc",它将很高兴地返回1.23,而没有向您指示传入的String包含不可解析的字符。在某些情况下,这实际上可能是理想的,但我认为通常它不是理想的行为。
对于TURKEY,您应该使用NumberFormat.getInstance(new Locale(tr_TR))
Java是否使用十进制作为默认值来处理数字?这就是为什么它失败了吗?
有关谁使用哪种分隔符的信息,请参见en.wikipedia.org/w/
当小数点分隔符是点(。)时,它将以旧的方式转换。例如2110.0转换为21100
您可以使用它(法语语言环境的小数点分隔符为,)
NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
nf.parse(p);
或者,您可以使用java.text.DecimalFormat并设置适当的符号:
DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(',');
symbols.setGroupingSeparator(' ');
df.setDecimalFormatSymbols(symbols);
df.parse(p);
是的...如果我们不设置千位分隔符,而仅使用法语格式,则西班牙语格式的数字(1.222.222,33)将转换为" 1 222 222,33",这不是我想要的。那谢谢啦!
另一件事是,西班牙语言环境未列为"默认值",并且我无法使用new Locale("es","ES")构造具有正确格式的Locale,然后自动使用NumberFormat(以,作为小数点分隔符和< x4>作为千位分隔符,只有DecimalFormat起作用。
为什么不是所有国家都在那里?我对使用法语语言环境设置波兰数字格式感到奇怪...
正如E-Riz所指出的,NumberFormat.parse(String)将" 1,23abc"解析为1.23。要获取全部输入,我们可以使用:
public double parseDecimal(String input) throws ParseException{
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.getDefault());
ParsePosition parsePosition = new ParsePosition(0);
Number number = numberFormat.parse(input, parsePosition);
if(parsePosition.getIndex() != input.length()){
throw new ParseException("Invalid input", parsePosition.getIndex());
}
return number.doubleValue();
}
此处详细说明了该策略:ibm.com/developerworks/library/j-numberformat
Double.parseDouble(p.replace(',','.'))
...非常快,因为它逐个字符地搜索基础字符数组。字符串替换版本会编译RegEx进行评估。
基本上,replace(char,char)大约快10倍,并且由于您将在低级代码中执行这些操作,因此考虑一下是有意义的。热点优化器无法解决问题……当然不在我的系统上。
如果您不知道正确的语言环境,并且字符串可以有千位分隔符,那么这可能是最后的选择:
doubleStrIn = doubleStrIn.replaceAll("[^\\d,\\.]++","");
if (doubleStrIn.matches(".+\\.\\d+,\\d+$"))
return Double.parseDouble(doubleStrIn.replaceAll("\\.","").replaceAll(",","."));
if (doubleStrIn.matches(".+,\\d+\\.\\d+$"))
return Double.parseDouble(doubleStrIn.replaceAll(",",""));
return Double.parseDouble(doubleStrIn.replaceAll(",","."));
请注意:这将很高兴地将字符串解析为" R 1 52.43,2"至" 15243.2"。
这是我在自己的代码中使用的静态方法:
public static double sGetDecimalStringAnyLocaleAsDouble (String value) {
if (value == null) {
Log.e("CORE","Null value!");
return 0.0;
}
Locale theLocale = Locale.getDefault();
NumberFormat numberFormat = DecimalFormat.getInstance(theLocale);
Number theNumber;
try {
theNumber = numberFormat.parse(value);
return theNumber.doubleValue();
} catch (ParseException e) {
// The string value might be either 99.99 or 99,99, depending on Locale.
// We can deal with this safely, by forcing to be a point for the decimal separator, and then using Double.valueOf ...
//http://stackoverflow.com/questions/4323599/best-way-to-parsedouble-with-comma-as-decimal-separator
String valueWithDot = value.replaceAll(",",".");
try {
return Double.valueOf(valueWithDot);
} catch (NumberFormatException e2) {
// This happens if we're trying (say) to parse a string that isn't a number, as though it were a number!
// If this happens, it should only be due to application logic problems.
// In this case, the safest thing to do is return 0, having first fired-off a log warning.
Log.w("CORE","Warning: Value is not a number" + value);
return 0.0;
}
}
}
如果默认的语言环境是类似德语的逗号分隔的小数点,该怎么办?您可以传入例如" 1,000,000",它不会解析为德语语言环境,然后将其替换为" 1.000.000",这不是有效的Double。
@jimmycar,您好,Ive刚刚更新了我的答案,以使用当前版本的静态方法。希望这能解决您的问题!皮特
您当然需要使用正确的语言环境。这个问题会有所帮助。
这将完成工作:
Double.parseDouble(p.replace(',','.'));
如果您认为replace与使用replaceAll明显不同,那么最初的问题是:"是否有比" p = p.replaceAll(",","。");更好的方法来解析" 1,234"以获取1.234。 ,请说明原因。