Проверка цифр с определенным десятичным разделителем

#c# #linq

#c# #linq

Вопрос:

У меня есть функция, как показано ниже (я не очень знаком с linq)

     public static bool IsNumber(string s, char dec_sep)
    {
        return s.Length > 0 amp;amp; s.All(c => Char.IsDigit(c));
    }
  

Если число содержит десятичный разделитель, я получаю false как факт.
Я хочу проверить, находится ли мой определенный десятичный разделитель в числе
Возможно ли изменить эту функцию для этой цели?
Или я должен написать другую функцию?

Для большей ясности

Если в строке есть десятичный разделитель, такой как 72.5, он возвращает false (мой определенный разделитель — «.» ). Он уже возвращает true, если строка равна 72 или 725. Я хочу, чтобы эта функция возвращала значение TRUE даже с десятичным разделителем.

Комментарии:

1. Что вы пытаетесь здесь сделать? Вы пытаетесь проанализировать строку, представляющую десятичное число?

2. Можете ли вы объяснить это немного подробнее, я не понимаю, чего вы хотите?

3. Что, если у вас есть два десятичных разделителя? Почему бы не использовать уже встроенный float.TryParse ?

4. А как насчет разделителей тысяч? На моем языке (и многих других) 1,234.56 является совершенно допустимым числом…. Как насчет культурных различий? Что, если кто-то захочет использовать арабские или тайские цифры? Например, — สามสิบเอ็ด означает 31 на тайском языке (по крайней мере, согласно этому веб-сайту ) и ٧٧٥٤٢ равно 77 542…

5. @ZoharPeled Запятая, которую я использую для особых целей в своей программе, поэтому я ограничился точкой. Поэтому я не использую culturalinfo для выбора десятичного разделителя.

Ответ №1:

Я бы не советовал писать свою собственную функцию «IsNumber».

В фреймворке уже есть TryParse все встроенные типы значений, поэтому я предлагаю использовать либо float.TryParse , double.TryParse либо decimal.TryParse в зависимости от размера и точности числа, которое вы ожидаете (23, 64 или 128 бит).

Написание вашей собственной функции «IsNumber» неизбежно вызовет некоторые трудности, особенно если вы собираетесь попытаться проанализировать пользовательский ввод (или любой ввод, который вы не можете контролировать, если на то пошло) — потому что, как и многие другие «простые» вещи, числа не что иное, как простые.

Во-первых, числа могут иметь разделитель тысяч — на английском языке 1234,56 является допустимым числом.
Во-вторых, строковые представления чисел зависят от культуры — 1,234.56 недопустимо в некоторых культурах, где десятичным разделителем является запятая, а разделителем тысяч является точка, поэтому на самом деле вы бы написали это так: 1,234,56
Обратите внимание, что это два разных способа записи одного и того же числа — одна тысяча двести тридцать четыре и пятьдесят шесть сотых.
Еще хуже, вы можете записать одно и то же число совершенно разными цифрами — тайским, арабским, китайским или ивритом — все эти языки (и, вероятно, многие другие языки) имеют свои собственные символы для чисел — и я не уверен, что это IsDigit охватывает их все (хотя, вероятно, это также зависит от культуры).


Сказав все это, ваша текущая функция выдаст a NullReferenceException , если строка равна нулю — самое меньшее, что вы должны сделать, это либо выдать ArgumentNullException , либо просто вернуть false, если строка равна нулю.
Более того, будет допустимый вариант использования, когда вы хотите знать, существует ли символ с точностью до нуля или один раз в строке — один из способов сделать это путем вычитания IndexOf из LastIndexOf и проверки того, что результат этого вычитания 0 . Чтобы объединить это с вашим текущим методом, вы также хотите изменить условие в All методе, чтобы разрешить символу быть либо цифрой, либо назначенным вами десятичным разделителем.

Если вам действительно нужно написать свой собственный метод, вот как я бы его запустил:

 public static bool IsNumber(string s, char dec_sep)
{
    return !string.IsNullOrEmpty(s)
        amp;amp; s.LastIndexOf(dec_sep) - s.IndexOf(dec_sep) == 0 
        amp;amp; s.All(c => Char.IsDigit(c) || c == dec_sep);
} 
  

Первое условие вернет значение false, если строка равна нулю или пуста,

второй вернет значение false, только если строка содержит dec_sep более одного раза,

и третий вернет false, только если строка содержит какой-либо символ, который не является ни цифрой, ни dec_sep .

Комментарии:

1. Спасибо, это то, что мне нужно. Я написал другую функцию, но мне нравится этот трюк linq

2. Здесь нет никакого трюка linq. Единственной частью linq в этом является s.All

Ответ №2:

Если вы поклонник регулярных выражений, вы также можете попробовать "^\d \.??(\d*)?$"