IT이야기

쉼표를 소수 구분 기호로 사용하여 이중을 구문 분석하는 가장 좋은 방법입니다.

cyworld 2022. 6. 7. 21:33
반응형

쉼표를 소수 구분 기호로 사용하여 이중을 구문 분석하는 가장 좋은 방법입니다.

콤마소수 구분자로 사용되기 때문에 이 코드는 다음과 같이 느려집니다.

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

더 나은 해석 방법은 없을까?"1,234"갖기 위해1.234그 이상:p = p.replaceAll(",",".");?

java.text를 사용합니다.숫자 형식:

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

갱신일 :

다국어 앱을 지원하려면 다음을 사용하십시오.

NumberFormat format = NumberFormat.getInstance(Locale.getDefault());

이것을 사용할 수 있습니다(프랑스 로케일은,소수 구분 기호)

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

또는 다음과 같은 적절한 기호를 사용하여 설정할 수 있습니다.

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

E-Riz가 지적한 바와 같이 번호format.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();
}
Double.parseDouble(p.replace(',','.'))

...는 기본 문자 배열을 문자 단위로 검색하기 때문에 매우 빠릅니다.문자열 치환 버전은 평가할 RegEx를 컴파일합니다.

기본적으로 치환(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;
        }
    }
}

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

그것은 쉽고 보편적이다!

물론 올바른 로케일을 사용해야 합니다. 질문이 도움이 될 거예요.

수신된 문자열 값의 로케일을 알 수 없고 현재 기본 로케일과 반드시 같은 로케일이 아닐 경우 다음을 사용할 수 있습니다.

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

}

문자열의 로케일에 관계없이 이중으로 반환됩니다.쉼표나 점이 몇 개라도 상관없습니다.그래서 지나간다1,000,000.54효과가 있을 것이다1.000.000,54따라서 문자열을 구문 분석할 때 기본 로케일에 의존할 필요가 없습니다.코드가 최대한 최적화되어 있지 않기 때문에 어떤 제안이라도 환영합니다.문제가 해결되었는지 확인하기 위해 대부분의 케이스를 테스트해 보았지만, 모든 것을 커버할 수 있을지 모르겠습니다.한계값이 발견되면 알려주세요.

이렇게 하면 됩니다.

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

언급URL : https://stackoverflow.com/questions/4323599/best-way-to-parsedouble-with-comma-as-decimal-separator

반응형