Java 使用逗号作为小数分隔符解析Double的最佳方法?
以下是导致异常的Java 使用逗号作为小数分隔符解析Double的最佳方法?,java,Java,以下是导致异常的: String p="1,234"; Double d=Double.valueOf(p); System.out.println(d); 是否有比:p=p.replaceAll(“,”,”)更好的方法来解析“1234”以获得1.234?您可以使用它(法语区域设置有,表示十进制分隔符) 或者,您可以使用并设置适当的符号: DecimalFormat df = new DecimalFormat(); DecimalFormatSymbols symbols = new De
:
String p="1,234";
Double d=Double.valueOf(p);
System.out.println(d);
是否有比:p=p.replaceAll(“,”,”)更好的方法来解析“1234”
以获得1.234
代码>?您可以使用它(法语区域设置有,
表示十进制分隔符)
或者,您可以使用并设置适当的符号:
DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(',');
symbols.setGroupingSeparator(' ');
df.setDecimalFormatSymbols(symbols);
df.parse(p);
使用:
更新:
要支持多语言应用,请使用:
NumberFormat format = NumberFormat.getInstance(Locale.getDefault());
当然,您需要使用正确的区域设置。问题会有所帮助。正如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();
}
这是我在自己的代码中使用的静态方法:
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;
}
}
}
如果您不知道正确的语言环境,并且字符串可能有1000个分隔符,这可能是最后的选择:
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(",", "."));
请注意:这将很好地解析字符串,如“R152.43,2”到“15243.2”。这将完成以下工作:
Double.parseDouble(p.replace(',','.'));
…非常快速,因为它在逐字符的基础上搜索基础字符数组。字符串replace versions编译一个正则表达式进行计算
基本上,replace(char,char)大约快10倍,因为您将在低级代码中执行此类操作,所以考虑一下这一点是有意义的。热点乐观主义者不会明白这一点。。。当然,在我的系统上没有。如果您不知道收到的字符串值的区域设置,并且该区域设置不一定与当前默认区域设置相同,则可以使用以下方法:
private static double parseDouble(String price){
String parsedStringDouble;
if (price.contains(",") && price.contains(".")){
int indexOfComma = price.indexOf(",");
int indexOfDot = price.indexOf(".");
String beforeDigitSeparator;
String afterDigitSeparator;
if (indexOfComma < indexOfDot){
String[] splittedNumber = price.split("\\.");
beforeDigitSeparator = splittedNumber[0];
afterDigitSeparator = splittedNumber[1];
}
else {
String[] splittedNumber = price.split(",");
beforeDigitSeparator = splittedNumber[0];
afterDigitSeparator = splittedNumber[1];
}
beforeDigitSeparator = beforeDigitSeparator.replace(",", "").replace(".", "");
parsedStringDouble = beforeDigitSeparator+"."+afterDigitSeparator;
}
else {
parsedStringDouble = price.replace(",", "");
}
return Double.parseDouble(parsedStringDouble);
}
private static double parseDouble(字符串价格){
字符串parsedStringDouble;
if(price.contains(“,”&&price.contains(“.”)){
int indexOfComma=price.indexOf(“,”);
int indexOfDot=价格。indexOf(“.”);
DigitSeparator之前的字符串;
弦后分离器;
if(indexOfComma
无论字符串的区域设置是什么,它都将返回一个double。不管有多少逗号或点。因此,传递1000000.54
将起作用,因此1.000.000,54
将起作用,因此您不必再依赖默认区域设置来解析字符串。代码并没有尽可能优化,所以欢迎任何建议。我试图测试大多数案例,以确保它解决了问题,但我不确定它是否涵盖了所有问题。如果你发现一个突破性的价值让我知道 在Kotlin中,您可以使用以下扩展:
fun String.toDoubleEx() : Double {
val decimalSymbol = DecimalFormatSymbols.getInstance().decimalSeparator
return if (decimalSymbol == ',') {
this.replace(decimalSymbol, '.').toDouble()
} else {
this.toDouble()
}
}
您可以在代码中的任何地方使用它,如下所示:
val myNumber1 = "5,2"
val myNumber2 = "6.7"
val myNum1 = myNumber1.toDoubleEx()
val myNum2 = myNumber2.toDoubleEx()
这是简单和普遍的 仅当当前默认区域设置恰好使用逗号作为十进制分隔符时,此选项才有效。为了进一步搞乱,某些区域设置使用逗号作为千位分隔符,在这种情况下,“1234”将解析为1234.0,而不是抛出错误。NumberFormat的问题是它将自动忽略无效字符。因此,如果您尝试解析“1,23abc”,它将愉快地返回1.23,而不会向您指示传入的字符串包含不可解析的字符。在某些情况下,这实际上可能是可取的,但我认为这通常不是理想的行为。对于土耳其,您应该使用NumberFormat.getInstance(新语言环境(tr_tr)),对于使用Separator的人,正如您所建议的,replaceAll()是最好的方法。它不依赖于当前的语言环境,它很简单,而且有效。@Marco Altieri:replaceAll(“,”,“)
用点替换所有逗号。如果没有逗号,那么它什么也不做Double.valueOf()
仅适用于使用点作为小数分隔符的字符串。此处的内容不受当前默认区域设置的影响。replaceAll(“,”,“)
的唯一问题是,它只有在只有一个逗号时才起作用:ie:1234567将抛出java.lang.NumberFormatException:多个点
。具有正向前瞻的正则表达式将满足p.replaceAll(“,(?=[0-9]+,)”,“)。replaceAll(“,”,”)
更多信息:没有问题。NumberFormatException很好。你怎么知道哪个逗号是正确的?格式错误,您所能做的就是向用户显示一条比异常更可读的消息。@不可读,格式没有错误。有些语言环境使用逗号作为千位分隔符,因此一个数字中可以有多个逗号,从技术上讲,它仍然是有效的输入。如果默认语言环境类似于德语,其中逗号表示小数点,该怎么办?您可以传入,例如“1000000”,它不会解析为德语语言环境,然后会被“1.000.000”替换,而“1.000.000”不是有效的双精度。我希望这能解决你的问题!Pete这里详细解释了这一策略:最初的问题是“有没有比:p=p.replaceAll(“,”,“);”更好的方法来解析“1234”以得到1.234,如果您认为replace
与使用replaceAll
有显著不同,请解释原因。是的。。。如果我们不设置千分组分隔符,只使用法语格式,西班牙语格式的数字(1.222.222,33)将转换为“1 222,33”,这不是我想要的。谢谢!另一件事是,西班牙语语言环境没有被列为“默认”,我不能用新语言环境(“es”,“es”)
构建格式正确的语言环境
private static double parseDouble(String price){
String parsedStringDouble;
if (price.contains(",") && price.contains(".")){
int indexOfComma = price.indexOf(",");
int indexOfDot = price.indexOf(".");
String beforeDigitSeparator;
String afterDigitSeparator;
if (indexOfComma < indexOfDot){
String[] splittedNumber = price.split("\\.");
beforeDigitSeparator = splittedNumber[0];
afterDigitSeparator = splittedNumber[1];
}
else {
String[] splittedNumber = price.split(",");
beforeDigitSeparator = splittedNumber[0];
afterDigitSeparator = splittedNumber[1];
}
beforeDigitSeparator = beforeDigitSeparator.replace(",", "").replace(".", "");
parsedStringDouble = beforeDigitSeparator+"."+afterDigitSeparator;
}
else {
parsedStringDouble = price.replace(",", "");
}
return Double.parseDouble(parsedStringDouble);
}
fun String.toDoubleEx() : Double {
val decimalSymbol = DecimalFormatSymbols.getInstance().decimalSeparator
return if (decimalSymbol == ',') {
this.replace(decimalSymbol, '.').toDouble()
} else {
this.toDouble()
}
}
val myNumber1 = "5,2"
val myNumber2 = "6.7"
val myNum1 = myNumber1.toDoubleEx()
val myNum2 = myNumber2.toDoubleEx()