Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用逗号作为小数分隔符解析Double的最佳方法?_Java - Fatal编程技术网

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