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

Int32.Parse vs Single.Parse - ( "1,234" ) и ( "1,2,3,4" ). Почему типы int и float разделяют символы разделителя по-разному?

В С#:

Это выдает a FormatException, который, похоже, не должен:

Int32.Parse("1,234");

Это не так, как обычно:

Single.Parse("1,234");

И удивительно, что это отлично разбирается:

Single.Parse("1,2,3,4"); //Returns 1234

Моя локальная культура - EN-US, поэтому , - разделитель тысяч по умолчанию char.

Основной вопрос: Почему непоследовательность?

Также: Почему работает Parse("1,2,3,4")? По-видимому, перед разбором просто удаляются все экземпляры локального разделителя char. Я знаю, что дополнительные избыточные накладные расходы будут выполняться в регулярном выражении или что-то в этом роде, но когда числовой литерал "1,2,3,4" не будет опечаткой?


по теме: С# Decimal.Parse issue с ​​запятыми

4b9b3361

Ответ 1

Согласно MSDN:

Параметр s содержит номер формы:

[ws] [знак] цифры [ws]


Параметр s интерпретируется с использованием стиля NumberStyles.Integer. В дополнение к десятичным разрядам допускаются только ведущие и конечные пробелы вместе с ведущим знаком.

Что он, NumberStyles.Integer запрещает метод Parse использовать разделитель тысяч, тогда как Single.Parse использует по умолчанию NumberStyles.Float и NumberStyles.AllowThousands. Вы можете изменить это поведение, указав второй аргумент как NumberStyles:

Int32.Parse("1,234", NumberStyles.AllowThousands); //works

Single.Parse игнорирует группировку и вообще не использует специфическую для культуры NumberGroupSizes и определяет только, является ли символ разделителем группы или десятичной дроби. Размеры групп используются только при форматировании чисел.

Ответ 2

Для первого случая, Ссылка на исходный код Microsoft, по умолчанию Int32.Parse реализует NumberStyles.Integer, но не NumberStyles.AllowThousands

public static int Parse(String s) {
    return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}

Таким образом, любой разделитель запятой не допускается. Это:

Int32.Parse("1,234");

или

Int32.Parse("1.234"); 

оба будут ошибочными. В любой культуре.

Чтобы исправить это, NumberStyles.AllowThousands необходимо добавить в NumberStyles, который позволит анализировать "1,234" в культуре EN-US:

Int32.Parse("1,234", NumberStyles.Integer | NumberStyles.AllowThousands);

Но

Int32.Parse("1.234", NumberStyles.Integer | NumberStyles.AllowThousands);

Будет ли еще throw a Exception.


Для второго случая, в соответствии с ссылкой на источник кода Microsoft, стиль по умолчанию для Single.Parse:

public static float Parse(String s) {
    return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}

Что позволяет разделитель тысяч. И "," распознается как тысячный разделитель в культуре EN-US, для Single.Parse и, следовательно, вы правильно правильно разбираете второй случай

Single.Parse("1,234"); //OK

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


Что касается третьего случая, Internally, Single.Parse вызывает TryStringToNumber и Parse.Number, который просто игнорирует тысячи разделителей. Таким образом, вы получаете:

Single.Parse("1,2,3,4"); //Returns 1234 

Поскольку он эквивалентен как

Single.Parse("1234"); //Returns 1234 

Ответ 3

мой - es-ES На этих. это разделитель тысяч по умолчанию char и "," отдельный символ между int и double Так любой разбор вроде "1.2.3,4" дает мне "123,40" (123,40 долларов США) Если я поставлю "." перед ",", как "123,4,3", он дает ошибку но, точно так же, как говорится в ответах, если я ставлю "1.2.3.4", то дал мне "1234", Таким образом, возможно, это функциональность самой .net.