C # decimal.Parse поведение - PullRequest
       26

C # decimal.Parse поведение

7 голосов
/ 13 января 2011

Короткий вопрос:

Почему эти ' ..... ' действительны для анализа десятичного числа в .NET (C #):

decimal res = decimal.Parse("8......15");  // returns 815
decimal res = decimal.Parse("8...15");     // returns 815
decimal res = decimal.Parse("8..15");      // returns 815

В чем причина?

Ответы [ 3 ]

19 голосов
/ 13 января 2011

Это не для меня. Вы случайно не в культуре где "." разделитель тысяч и "," десятичная точка? Decimal.Parse (и аналогичные вызовы) по умолчанию используют текущую культуру потока. Независимо от того, что это хорошая вещь или нет, является спорным, но не имеет отношения к реальному поведению:)

Попробуйте указать CultureInfo.InvariantCulture в вызове decimal.Parse:

decimal res = decimal.Parse("8......15", CultureInfo.InvariantCulture);

Я считаю, что будет вести себя так, как вы ожидали.

2 голосов
/ 13 января 2011

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

Мы называем их разделителями тысяч, но они на самом делене.Они являются разделителями групп - вы можете разделить каждые 3 цифры, каждые 10 цифр, каждую 1 цифру, так почему бы не каждые 0 цифр?

Интересно, что код изменился для .NET 4 - это соответствующий вывод изОтражатель для меня:

else
{
    if (((currencySymbol == null) || 
         ((chPtr2 = MatchChars(p, currencySymbol)) == null)) && 
        ((ansiCurrencySymbol == null) || 
         ((chPtr2 = MatchChars(p, ansiCurrencySymbol)) == null)))
    {
        break;
    }
    num |= 0x20;
    currencySymbol = null;
    ansiCurrencySymbol = null;
    p = chPtr2 - 1;
}
1 голос
/ 13 января 2011

Я не знаю почему, но я знаю, как это работает (часть кода десятичного синтаксического анализатора см. Ниже).Я думаю, что еще, если просто включить флаг точки и пропустить все точки.

    while (true)
{
    if (((ch >= '0') && (ch <= '9')) || (((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None) && (((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F')))))
    {
        //Here goes some code...
    }
    else if ((((options & NumberStyles.AllowDecimalPoint) != NumberStyles.None) && ((num & 0x10) == 0)) 
    && (((chPtr2 = MatchChars(p, currencyDecimalSeparator)) != null) || ((flag && ((num & 0x20) == 0)) 
    && ((chPtr2 = MatchChars(p, numberDecimalSeparator)) != null))))
    {
        num |= 0x10;
        p = chPtr2 - 1;
    }
}

Используйте инструмент Reflector для исследования всего кода.

...