Java 用逗号作为小数点分隔符解析Double的最佳方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4323599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:52:33  来源:igfitidea点击:

Best way to parseDouble with comma as decimal separator?

java

提问by Koerr

Following is resulting in an Exception:

以下是导致Exception

String p="1,234";
Double d=Double.valueOf(p); 
System.out.println(d);

Is there a better way to parse "1,234"to get 1.234than: p = p.replaceAll(",",".");?

有没有更好的方法来分析"1,234",以得到1.234比:p = p.replaceAll(",",".");

采纳答案by dogbane

Use java.text.NumberFormat:

使用java.text.NumberFormat

NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
Number number = format.parse("1,234");
double d = number.doubleValue();

回答by Bozho

You can use this (the French locale has ,for decimal separator)

您可以使用它(法语语言环境有,十进制分隔符)

NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
nf.parse(p);

Or you can use java.text.DecimalFormatand set the appropriate symbols:

或者您可以使用java.text.DecimalFormat和设置适当的符号:

DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(',');
symbols.setGroupingSeparator(' ');
df.setDecimalFormatSymbols(symbols);
df.parse(p);

回答by kgiannakakis

You of course need to use the correct locale. Thisquestion will help.

您当然需要使用正确的语言环境。这个问题会有所帮助。

回答by dgolive

As E-Riz points out, NumberFormat.parse(String) parse "1,23abc" as 1.23. To take the entire input we can use:

正如 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();
}

回答by Pete

This is the static method I use in my own code:

这是我在自己的代码中使用的静态方法:

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;
        }
    }
}

回答by user3506443

If you don't know the correct Locale and the string can have a thousand separator this could be a last resort:

如果您不知道正确的 Locale 并且字符串可以有千位分隔符,这可能是最后的手段:

    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(",", "."));

Be aware: this will happily parse strings like "R 1 52.43,2" to "15243.2".

请注意:这会很高兴地将诸如“R 1 52.43,2”之类的字符串解析为“15243.2”。

回答by Helge

This would do the job:

这将完成这项工作:

Double.parseDouble(p.replace(',','.')); 

回答by RocketBanana

Double.parseDouble(p.replace(',','.'))

...is very quick as it searches the underlying character array on a char-by-char basis. The string replace versions compile a RegEx to evaluate.

...非常快,因为它逐个字符地搜索底层字符数组。字符串替换版本编译一个 RegEx 来评估。

Basically replace(char,char) is about 10 times quicker and since you'll be doing these kind of things in low-level code it makes sense to think about this. The Hot Spot optimiser will not figure it out... Certainly doesn't on my system.

基本上 replace(char,char) 大约快 10 倍,因为您将在低级代码中做这些事情,所以考虑这一点是有道理的。Hot Spot 优化器不会解决这个问题...在我的系统上肯定不会。

回答by Amro elaswar

In the case where you don't know the locale of the string value received and it is not necessarily the same locale as the current default locale you can use this :

如果您不知道收到的字符串值的语言环境,并且它不一定与当前默认语言环境相同,您可以使用以下命令:

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

}

It will return a double no matter what the locale of the string is. And no matter how many commas or points there are. So passing 1,000,000.54will work so will 1.000.000,54so you don't have to rely on the default locale for parsing the string anymore. The code isn't as optimized as it can be so any suggestions are welcome. I tried to test most of the cases to make sure it solves the problem but I am not sure it covers all. If you find a breaking value let me know.

无论字符串的语言环境是什么,它都会返回一个双精度值。无论有多少逗号或点。因此传递1,000,000.54将起作用,1.000.000,54因此您不必再依赖默认语言环境来解析字符串。代码没有尽可能优化,因此欢迎提出任何建议。我试图测试大多数情况以确保它解决了问题,但我不确定它是否涵盖了所有情况。如果你发现了一个突破性的价值,让我知道。