Подтвердить что ты не робот

Разбор строк удваивается запятой и точкой

Я пытаюсь написать функцию, которая в основном преобразует массив строк в массив строк, где все удвои в массиве округлены до количества десятичных мест, которые я задал. Также могут быть строки в массиве, которые вообще не являются двойными значениями.

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" будет обрабатывать запятую неправильно. У кого-нибудь есть простое и эффективное решение для этого?

4b9b3361

Ответ 1

Вы хотите обрабатывать точку (.) как запятую (,). Итак, замените

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

с

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

Ответ 2

Лечить и то, и другое. как десятичную точку, вы должны не только заменить ее на другую, но также убедиться, что используемый синтаксический анализ Culture интерпретирует ее как десятичную точку.

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

Ответ 3

Вам НЕ НУЖНО заменить запятую и точку..

У меня была та же проблема. Причина проста: культура конверсии играет большую роль в интерпретации запятой или точки. Я использую немецкую культуру, где запятая различает дроби, где, как и везде, точка работает.

Здесь я сделал полный пример, чтобы прояснить разницу.

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

Результаты следующие: enter image description here

Поиграйте с культурой, и вы получите желаемый результат.

Ответ 4

Проблема заключается в том, что вы (или система) не можете отличить десятичный разделитель от разделителя тысяч, когда они могут быть как запятой, так и точкой. Например:

В моей культуре

1.123 - нормальное обозначение для числа выше 1000; в то время как

1,123 - число вблизи 1.

Использование инвариантной культуры по умолчанию использует точку в качестве десятичного разделителя. В общем, вы должны убедиться, что все числа написаны с использованием одной и той же постоянной культуры во всех системах (например, инвариантная культура).

Если вы уверены, что ваши номера никогда не содержат ничего, кроме запятой или точкой для десятичного разделителя (т.е. разделителей тысяч), я бы String.Replace() запятую с точкой и выполняю остальные так же, как и вы.

В противном случае вам будет сложно программировать что-то, что может отличить 1.123 от 1,123, не зная культуры.

Ответ 5

Создайте две статичные культуры: одну для запятой и одну для точки.

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

Это должно работать, даже если среда и культура хоста меняются.

Ответ 6

Используйте эту перегрузку double.TryParse, чтобы указать разрешенные форматы:

Double.TryParse Method (String, NumberStyles, IFormatProvider, Double%)

По умолчанию double.TryParse будет анализироваться на основе существующих форматов культуры.

Ответ 7

Расширение для разбора десятичного числа из строки.

  • Независимо от того, будет ли номер в начале, в конце или в середине строки.
  • Независимо от того, будет ли только количество или количество букв "мусора".
  • Независимо от того, какой разделитель настроен в культурных настройках на ПК: он правильно проанализирует точку и запятую.
  • Возможность установки десятичного символа вручную.

    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 4.45 O'clock now".DoubleParseAdvanced(); // will return 4.45
"It 4,45 O'clock now".DoubleParseAdvanced(); // will return 4.45
"It 4:45 O'clock now".DoubleParseAdvanced(':'); // will return 4.45

Ответ 8

Вы можете проверить, содержит ли строка десятичную точку, используя

string s="";

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

а затем рассмотрим это как десятичное значение, иначе просто передайте недвоенное значение.

Ответ 9

попробуйте это... он работает для меня.

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