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 с запятыми
Ответы
Ответ 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.