Как преобразовать иностранные строковые представления числа с десятичными числами в двойные? - PullRequest
2 голосов
/ 21 августа 2010

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

  • Франция: 1 234 567,89 == 1 234 567,89
  • Германия: 1,234,567,89 == 1 234 567,89
  • Австралия: 1 234 567,89 == 1 234 567,89

Я почти уверен, что именно так эти страны могут представлять десятичные числа. Если не извините. Точка 1 234 567,89 может быть представлена ​​многими способами.

Что я хотел бы сделать, так это убедиться, что любое строковое представление десятичного числа, которое я пытаюсь разобрать, должно получиться 1 234 567,89.

Я думал, что хорошим способом для этого было бы использование метода double.TryParse(), но я не смог заставить его работать.

Вот что я получил в небольшом тестовом приложении:

double num;
Console.WriteLine(double.TryParse("1 234 567,89", NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out num).ToString());
Console.WriteLine(num.ToString());
Console.WriteLine(double.TryParse("1.234.567,89", NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out num).ToString());
Console.WriteLine(num.ToString());
Console.WriteLine(double.TryParse("1 234 567.89", NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out num).ToString());
Console.WriteLine(num.ToString());

Все, что я делаю, это проверяю, что TryParse работает, а затем печатаю номер. В этом случае TryParse всегда выдает false. Значение false означает, что TryParse перехватило FormatException и, очевидно, не удалось преобразовать строку в двойное число.

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

У меня сложилось впечатление, что, сказав NumberStyles.Any, это означает, что строка может быть в любой форме десятичного числа. У меня также сложилось впечатление, что высказывание CultureInfo.InvariantCulture.NumberFormat возвращает информацию о форматировании чисел, которые являются культурно независимыми. Другими словами, он создаст десятичную форму вида 1 234 567,89.

Спасибо, что нашли время прочитать мою проблему. Любая помощь будет высоко ценится.

Ответы [ 4 ]

2 голосов
/ 21 августа 2010

Разные культуры имеют разные разделители тысяч, десятичные разделители и многое другое, поэтому вам нужно использовать соответствующий CultureInfo для культуры.

Вы используете InvariantCulture для всех из них - это означает отсутствие культуры вообще, и по умолчанию конкретные числовые разделители такие же, как и для en-US.

Например, если вы хотите проанализировать число в французском формате, пример взят из MSDN (слегка изменено):

double number;
string value = "1345,978";
NumberStyle style = NumberStyles.AllowDecimalPoint;
CultureInfo culture = CultureInfo.CreateSpecificCulture("fr-FR");
if (Double.TryParse(value, style, culture, out number))
   Console.WriteLine("Converted '{0}' to {1}.", value, number);

Отображение:

Преобразовано «1345,978» в 1345,978.

1 голос
/ 21 августа 2010

Это делает работу в любом сценарии.Его немного разбор.

List<string> inputs = new List<string>()
{
    "1.234.567,89",
    "1 234 567,89",
    "1 234 567.89",
    "1,234,567.89",
    "123456789",
    "1234567,89",
    "1234567.89",
};
string output;

foreach (string input in inputs)
{
    // unify string (no spaces, only . )
    output = input.Trim().Replace(" ", "").Replace(",", ".");

    // split it on points
    string[] split = output.Split('.');

    if (split.Count() > 1)
    {
        // take all parts except last
        output = string.Join("", split.Take(split.Count()-1).ToArray());

        // combine token parts with last part
        output = string.Format("{0}.{1}", output, split.Last());
    }

    // parse double invariant
    double d = double.Parse(output, CultureInfo.InvariantCulture);
    Console.WriteLine(d);
}
0 голосов
/ 21 августа 2010

Я бы предложил, чтобы вы все согласились на CultureInfo.InvariantCulture.NumberFormat. Вы можете попробовать некоторые формальные спецификации, такие как XSD, которые могут быть проверены автоматически.

0 голосов
/ 21 августа 2010

Если вы всегда гарантированно получаете центы 1 234 567,00, вы можете игнорировать все знаки препинания

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...