programing

쉼표와 포인트를 사용하여 문자열을 이중으로 구문 분석

procenter 2021. 1. 16. 10:43
반응형

쉼표와 포인트를 사용하여 문자열을 이중으로 구문 분석


기본적으로 문자열 배열을 문자열 배열로 변환하는 함수를 작성하려고합니다. 여기서 배열의 모든 double은 내가 설정 한 소수 자릿수로 반올림됩니다. 배열에 double 값이 전혀없는 문자열이있을 수도 있습니다.

string[,] values = new string[1, 3];

values[0, 0] = "hello";
values[0, 1] = "0.123";
values[0, 2] = "0,123";

int decimalPlaces = 2;

double tmp;
string format = "F" + decimalPlaces.ToString();
IFormatProvider provider = CultureInfo.InvariantCulture;
for (int i = 0; i < values.GetLength(0); i++)
{
    for (int j = 0; j < values.GetLength(1); j++)
    {
        if (double.TryParse(values[i, j], out tmp))
        {
            values[i, j] = tmp.ToString(format, provider);
        }
    }
}

Console.ReadLine();

결과는 "hello", "0.12", "0.12"여야하지만 "hello", "123.00", "0.12"는 쉼표를 잘못된 방식으로 처리합니다. 누구든지 이것에 대한 간단하고 효율적인 솔루션이 있습니까?


점 ( .)을 쉼표 ( ,) 처럼 처리하려고합니다 . 그래서 교체

if (double.TryParse(values[i, j], out tmp))

if (double.TryParse(values[i, j].Replace('.', ','), out tmp))

, 및. 소수점으로 하나를 다른 것으로 바꿔야 할뿐만 아니라 Culture에서 사용한 구문 분석이 소수점으로 해석하는지 확인해야합니다.

text = text.Replace(',', '.');
return double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out value);

쉼표와 점을 바꿀 필요가 없습니다 ..

나는 똑같은 문제를 겪었습니다. 그 이유는 간단합니다. 쉼표 나 점이 해석되는 전환 문화가 큰 역할을합니다. 나는 쉼표가 분수를 구별하는 독일 문화를 사용하는데, 다른 곳에서는 점이 일을합니다.

여기에서 차이점을 명확히하기 위해 완전한 예를 만들었습니다.

string[] doubleStrings = {"hello", "0.123", "0,123"};
double localCultreResult;
foreach (var doubleString in doubleStrings)
{
    double.TryParse(doubleString, NumberStyles.Any, CultureInfo.CurrentCulture, out localCultreResult);
    Console.WriteLine(string.Format("Local culture results for the parsing of {0} is {1}", doubleString, localCultreResult));
}

double invariantCultureResult;
foreach (var doubleString in doubleStrings)
{
    double.TryParse(doubleString, NumberStyles.Any, CultureInfo.InvariantCulture, out invariantCultureResult);
    Console.WriteLine(string.Format("Invariant culture results for the parsing of {0} is {1}", doubleString, invariantCultureResult));
}

결과는 다음과 같습니다. 여기에 이미지 설명 입력

문화를 가지고 놀면 필요한 결과를 얻을 수 있습니다.


문제는 사용자 (또는 시스템)가 쉼표 또는 점이 될 수있는 천 단위 구분 기호와 소수 구분 기호를 구분할 수 없다는 것입니다. 예를 들면 :

제 문화에서는

1.1231000 이상의 숫자에 대한 일반적인 표기법입니다. 이므로

1,123 1에 가까운 숫자입니다.

고정 문화권을 사용하면 점을 소수점 구분 기호로 사용하도록 기본 설정됩니다. 일반적으로 모든 숫자가 모든 시스템에서 동일한 상수 문화를 사용하여 작성되었는지 확인해야합니다 (예 : 불변 문화).

숫자에 소수점 구분 기호 (즉, 천 단위 구분 기호 없음)를위한 쉼표 또는 점 이외의 어떤 것도 포함되지 않는다고 확신하는 경우, 쉼표에 점을 추가 String.Replace()하고 나머지는 수행 한대로 수행합니다.

그렇지 않으면, 당신은 구별 할 수 있습니다 힘든 시간을 프로그래밍 뭔가해야합니다 1.123에서 1,123문화를 모르고 있습니다.


두 개의 정적 문화를 만드십시오. 하나는 쉼표 용이고 다른 하나는 포인트 용입니다.

    var commaCulture = new CultureInfo("en")
    {
        NumberFormat =
        {
            NumberDecimalSeparator = ","
        }
    };

    var pointCulture = new CultureInfo("en")
    {
        NumberFormat =
        {
            NumberDecimalSeparator = "."
        }
    };

그런 다음 입력 (함수 사용)에 따라 각각을 사용합니다.

    public double ConvertToDouble(string input)
    {
        input = input.Trim();

        if (input == "0") {
            return 0;
        }

        if (input.Contains(",") && input.Split(',').Length == 2)
        {
            return Convert.ToDouble(input, commaCulture);
        }

        if (input.Contains(".") && input.Split('.').Length == 2)
        {
            return Convert.ToDouble(input, pointCulture);
        }

        throw new Exception("Invalid input!");
    }

그런 다음 배열을 반복합니다.

    var strings = new List<string> {"0,12", "0.122", "1,23", "00,0", "0.00", "12.5000", "0.002", "0,001"};
    var doubles = new List<double>();

    foreach (var value in strings) {
        doubles.Add(ConvertToDouble(value));
    }

이는 호스트 환경과 문화가 변경 되더라도 작동합니다.


이 double.TryParse 오버로드를 사용하여 허용되는 형식을 지정합니다.

Double.TryParse 메서드 (String, NumberStyles, IFormatProvider, Double %)

기본적으로 double.TryParse는 현재 문화권 별 형식을 기반으로 구문 분석합니다.


문자열에서 10 진수를 구문 분석하는 확장입니다.

  • 숫자에 관계없이 문자열의 시작, 끝 또는 중간에 있습니다.
  • "쓰레기"글자가 많든 많든 상관 없습니다.
  • PC의 문화적 설정에 구성된 구분 기호가 무엇이든 상관없이 점과 쉼표를 모두 올바르게 구문 분석합니다.
  • 소수점 기호를 수동으로 설정하는 기능.

    public static class StringExtension
    {
        public static double DoubleParseAdvanced(this string strToParse, char decimalSymbol = ',')
        {
            string tmp = Regex.Match(strToParse, @"([-]?[0-9]+)([\s])?([0-9]+)?[." + decimalSymbol + "]?([0-9 ]+)?([0-9]+)?").Value;
    
            if (tmp.Length > 0 && strToParse.Contains(tmp))
            {
                var currDecSeparator = System.Windows.Forms.Application.CurrentCulture.NumberFormat.NumberDecimalSeparator;
    
                tmp = tmp.Replace(".", currDecSeparator).Replace(decimalSymbol.ToString(), currDecSeparator);
    
                return double.Parse(tmp);
            }
    
            return 0;
        }
    }
    

사용하는 방법:

"It's 4.45 O'clock now".DoubleParseAdvanced(); // will return 4.45
"It's 4,45 O'clock now".DoubleParseAdvanced(); // will return 4.45
"It's 4:45 O'clock now".DoubleParseAdvanced(':'); // will return 4.45

문자열에 소수점이 포함되어 있는지 확인할 수 있습니다.

string s="";

        if (s.Contains(','))
        { 
        //treat as double how you wish
        }

그런 다음 십진수로 취급하고 그렇지 않으면 double이 아닌 값을 전달하십시오.


이것을 시도하십시오 ... 그것은 나를 위해 작동합니다.

double vdouble = 0;
string sparam = "2,1";

if ( !Double.TryParse( sparam, NumberStyles.Float, CultureInfo.InvariantCulture, out vdouble ) )
{
    if ( sparam.IndexOf( '.' ) != -1 )
    {
        sparam = sparam.Replace( '.', ',' );
    }
    else
    {
        sparam = sparam.Replace( ',', '.' );
    }

    if ( !Double.TryParse( sparam, NumberStyles.Float, CultureInfo.InvariantCulture, out vdouble ) )
    {
        vdouble = 0;
    }
}

참조 URL : https://stackoverflow.com/questions/11560465/parse-strings-to-double-with-comma-and-point

반응형