Определите, является ли строка числом

579

Если у меня есть эти строки:

  1. "abc"= false

  2. "123"= true

  3. "ab2"= false

Есть ли такая команда, как IsNumeric() или что-то еще, которая может определить, является ли строка допустимым числом?

  • 77
    из их примеров вы можете видеть, что они имели в виду, если вся строка представляет число.
  • 36
    вернуть str.All (Char.IsDigit);
Показать ещё 6 комментариев
Теги:
string
parsing
isnumeric

23 ответа

905
Лучший ответ
int n;
bool isNumeric = int.TryParse("123", out n);

Обновление от С# 7:

var isNumeric = int.TryParse("123", out int n);

Варианты могут быть заменены их соответствующими типами!

  • 110
    Хотя я бы использовал double.TryParse, так как мы хотим знать, представляет ли он число вообще.
  • 4
    Функция вернет true, если я передам строку как «-123» или «+123». Я понимаю, что целое число имеет положительные и отрицательные значения. Но если эта строка исходит из введенного пользователем текстового поля, она должна вернуть false.
Показать ещё 7 комментариев
328

Это вернет true, если input - все числа. Не знаю, лучше ли это, чем TryParse, но он будет работать.

Regex.IsMatch(input, @"^\d+$")

Если вы просто хотите знать, имеет ли он одно или несколько чисел, смешанных с символами, оставьте значение ^ + и $.

Regex.IsMatch(input, @"\d")

Edit: На самом деле я думаю, что это лучше, чем TryParse, потому что очень длинная строка может потенциально переполнить TryParse.

  • 2
    Построить регулярное выражение раз и навсегда было бы гораздо эффективнее.
  • 2
    @CFP +1 ... RegEx всегда лучше, чем обычные функции, когда это применимо!
Показать ещё 11 комментариев
150

Вы также можете использовать:

stringTest.All(char.IsDigit);

Он вернет true для всех числовых цифр (не с float) и false если входная строка является какой-либо буквенно-цифровой.

Обратите внимание: stringTest не должен быть пустой строкой, так как это пройдет тест на числовость.

  • 13
    Это очень круто. Однако следует помнить одну вещь: пустая строка пройдет этот тест как числовой.
  • 2
    @ dan-gph: я рад, тебе нравится. Да вы правы. Я обновил примечание выше. Спасибо!
Показать ещё 3 комментария
113

Я использовал эту функцию несколько раз:

public static bool IsNumeric(object Expression)
{
    double retNum;

    bool isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
    return isNum;
}

Но вы также можете использовать;

bool b1 = Microsoft.VisualBasic.Information.IsNumeric("1"); //true
bool b2 = Microsoft.VisualBasic.Information.IsNumeric("1aa"); // false

От Benchmarking IsNumeric Options

alt text http://aspalliance.com/images/articleimages/80/Figure1.gif

alt text http://aspalliance.com/images/articleimages/80/Figure2.gif

  • 72
    ссылаясь на Microsoft.VisualBasic.dll из приложения C #? Eww: P
  • 0
    У меня нет проблем, чтобы использовать "IsNumeric", он работает хорошо. Также вы можете видеть, что есть небольшая разница в эффективности между TryParse и IsNumeric. Помните, что TryParse является новым в 2.0, и до этого было лучше использовать IsNumeric, чем любую другую стратегию.
Показать ещё 4 комментария
32

Это, вероятно, лучший вариант в С#.

Если вы хотите узнать, содержит ли строка целое число (целое число):

string someString;
// ...
int myInt;
bool isNumerical = int.TryParse(someString, out myInt);

Метод TryParse попытается преобразовать строку в число (целое число), и если она преуспеет, она вернет true и поместит соответствующий номер в myInt. Если он не может, он возвращает false.

Решения, использующие альтернативу int.Parse(someString), показанные в других ответах, работают, но это намного медленнее, потому что исключение бросания очень дорого. TryParse(...) был добавлен на язык С# в версии 2, и до этого у вас не было выбора. Теперь вы делаете: поэтому вам следует избегать альтернативы Parse().

Если вы хотите принять десятичные числа, десятичный класс также имеет метод .TryParse(...). Замените int на десятичное число в приведенном выше обсуждении, и применяются те же принципы.

24

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

Пример.

decimal myDec;
var Result = decimal.TryParse("123", out myDec);

Результат тогда = True

decimal myDec;
var Result = decimal.TryParse("abc", out myDec);

Результат тогда = False

  • 0
    Я думаю, что я мог сделать это больше в синтаксисе стиля VB, чем в C #, но применяются те же правила.
19

В случае, если вы не хотите использовать int.Parse или double.Parse, вы можете перевернуть свой код примерно так:

public static class Extensions
{
    public static bool IsNumeric(this string s)
    {
        foreach (char c in s)
        {
            if (!char.IsDigit(c) && c != '.')
            {
                return false;
            }
        }

        return true;
    }
}
  • 3
    Вы также можете вернуть s.All (c => c.IsDigit (c) || c == '.'), но ...
  • 5
    Что если они имеют в виду только целые числа? А как насчет мест где '.' разделитель группы, а не запятая (например, pt-Br)? как насчет отрицательных чисел? разделители групп (запятые на английском)? символы валюты? TryParse () может управлять всем этим, как требуется, используя NumberStyles и IFormatProvider.
Показать ещё 5 комментариев
14

Я знаю, что это старый поток, но ни один из ответов не сделал это для меня - либо неэффективным, либо не инкапсулированным для простого повторного использования. Я также хотел, чтобы он возвращал false, если строка была пустой или нулевой. TryParse возвращает true в этом случае (пустая строка не вызывает ошибку при разборе числа). Итак, здесь мой метод расширения строки:

public static class Extensions
{
    /// <summary>
    /// Returns true if string is numeric and not empty or null or whitespace.
    /// Determines if string is numeric by parsing as Double
    /// </summary>
    /// <param name="str"></param>
    /// <param name="style">Optional style - defaults to NumberStyles.Number (leading and trailing whitespace, leading and trailing sign, decimal point and thousands separator) </param>
    /// <param name="culture">Optional CultureInfo - defaults to InvariantCulture</param>
    /// <returns></returns>
    public static bool IsNumeric(this string str, NumberStyles style = NumberStyles.Number,
        CultureInfo culture = null)
    {
        double num;
        if (culture == null) culture = CultureInfo.InvariantCulture;
        return Double.TryParse(str, style, culture, out num) && !String.IsNullOrWhiteSpace(str);
    }
}

Прост в использовании:

var mystring = "1234.56789";
var test = mystring.IsNumeric();

Или, если вы хотите проверить другие типы номеров, вы можете указать "стиль". Итак, чтобы преобразовать число с помощью Exponent, вы можете использовать:

var mystring = "5.2453232E6";
var test = mystring.IsNumeric(style: NumberStyles.AllowExponent);

Или, чтобы проверить потенциальную шестнадцатеричную строку, вы можете использовать:

var mystring = "0xF67AB2";
var test = mystring.IsNumeric(style: NumberStyles.HexNumber)

Необязательный параметр "культура" может использоваться примерно таким же образом.

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

  • 1
    Прекрасно работает, за исключением того, что Double.TryParse не поддерживает NumberStyles.HexNumber. См. MSDN Double.TryParse. Любая причина, почему вы TryParse перед проверкой IsNullOrWhiteSpace? TryParse возвращает false, если IsNullOrWhiteSpace не так?
11

Если вы хотите поймать более широкий спектр чисел, à la PHP is_numeric, вы можете использовать следующее:

// From PHP documentation for is_numeric
// (http://php.net/manual/en/function.is-numeric.php)

// Finds whether the given variable is numeric.

// Numeric strings consist of optional sign, any number of digits, optional decimal part and optional
// exponential part. Thus +0123.45e6 is a valid numeric value.

// Hexadecimal (e.g. 0xf4c3b00c), Binary (e.g. 0b10100111001), Octal (e.g. 0777) notation is allowed too but
// only without sign, decimal and exponential part.
static readonly Regex _isNumericRegex =
    new Regex(  "^(" +
                /*Hex*/ @"0x[0-9a-f]+"  + "|" +
                /*Bin*/ @"0b[01]+"      + "|" + 
                /*Oct*/ @"0[0-7]*"      + "|" +
                /*Dec*/ @"((?!0)|[-+]|(?=0+\.))(\d*\.)?\d+(e\d+)?" + 
                ")$" );
static bool IsNumeric( string value )
{
    return _isNumericRegex.IsMatch( value );
}

Unit Test:

static void IsNumericTest()
{
    string[] l_unitTests = new string[] { 
        "123",      /* TRUE */
        "abc",      /* FALSE */
        "12.3",     /* TRUE */
        "+12.3",    /* TRUE */
        "-12.3",    /* TRUE */
        "1.23e2",   /* TRUE */
        "-1e23",    /* TRUE */
        "1.2ef",    /* FALSE */
        "0x0",      /* TRUE */
        "0xfff",    /* TRUE */
        "0xf1f",    /* TRUE */
        "0xf1g",    /* FALSE */
        "0123",     /* TRUE */
        "0999",     /* FALSE (not octal) */
        "+0999",    /* TRUE (forced decimal) */
        "0b0101",   /* TRUE */
        "0b0102"    /* FALSE */
    };

    foreach ( string l_unitTest in l_unitTests )
        Console.WriteLine( l_unitTest + " => " + IsNumeric( l_unitTest ).ToString() );

    Console.ReadKey( true );
}

Имейте в виду, что только потому, что значение является числовым, это не означает, что оно может быть преобразовано в числовой тип. Например, "999999999999999999999999999999.9999999999" является действительным числовым значением, но оно не будет вписываться в числовой тип .NET(не определенный в стандартной библиотеке, то есть).

  • 0
    Не пытаться быть умным alec здесь, но это похоже на ошибку для строки "0". Мое регулярное выражение не существует. Есть ли простая настройка для этого? Я получаю «0» и, возможно, «0.0» и даже «-0.0» в качестве возможных действительных чисел.
  • 0
    @ SteveHibbert - все знают, что «0» не число! Серьезно, хотя ... скорректировал регулярное выражение, чтобы соответствовать 0.
Показать ещё 4 комментария
9

Если вы хотите проверить, является ли строка номером (я предполагаю, что это строка, так как если это число, то вы знаете это одно).

  • Без регулярного выражения и
  • максимально использовать код Microsoft

вы также можете сделать:

public static bool IsNumber(this string aNumber)
{
     BigInteger temp_big_int;
     var is_number = BigInteger.TryParse(aNumber, out temp_big_int);
     return is_number;
}

Это позаботится об обычных гадости:

  • Минус (-) или Плюс (+) в начале
  • содержит десятичный символ BigIntegers не будет анализировать числа с десятичными точками. (Итак: BigInteger.Parse("3.3") выдаст исключение, а TryParse за то же самое вернет false)
  • Нет смешных цифр.
  • охватывает случаи, когда число больше обычного использования Double.TryParse

Вам нужно добавить ссылку на System.Numerics и иметь using System.Numerics; поверх вашего класса (ну, второй - бонус, который я предполагаю:)

8

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

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

Зачем? Потому что раздражает необходимость объявлять переменную out и проверять результат TryParse() прежде чем вы узнаете, произошел сбой анализа или нет. Я хочу использовать ternary operator чтобы проверить, является ли string numerical а затем просто проанализировать ее в первом троичном выражении или указать значение по умолчанию во втором троичном выражении.

Как это:

var doubleValue = IsNumeric(numberAsString) ? double.Parse(numberAsString) : 0;

Это просто намного чище, чем:

var doubleValue = 0;
if (double.TryParse(numberAsString, out doubleValue)) {
    //whatever you want to do with doubleValue
}

Я сделал несколько extension methods для этих случаев:


Метод расширения один

public static bool IsParseableAs<TInput>(this string value) {
    var type = typeof(TInput);

    var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
        new[] { typeof(string), type.MakeByRefType() }, null);
    if (tryParseMethod == null) return false;

    var arguments = new[] { value, Activator.CreateInstance(type) };
    return (bool) tryParseMethod.Invoke(null, arguments);
}

Пример:

"123".IsParseableAs<double>() ? double.Parse(sNumber) : 0;

Поскольку IsParseableAs() пытается проанализировать строку как соответствующий тип, а не просто проверяет, является ли строка "числовой", она должна быть довольно безопасной. И вы даже можете использовать его для нечисловых типов, у которых есть TryParse(), например DateTime.

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

Этот метод также может быть использован для простого разбора списка числовых строк в список типа double или некоторого другого типа со значением по умолчанию без необходимости перехвата каких-либо исключений:

var sNumbers = new[] {"10", "20", "30"};
var dValues = sNumbers.Select(s => s.IsParseableAs<double>() ? double.Parse(s) : 0);

Второй метод расширения

public static TOutput ParseAs<TOutput>(this string value, TOutput defaultValue) {
    var type = typeof(TOutput);

    var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
        new[] { typeof(string), type.MakeByRefType() }, null);
    if (tryParseMethod == null) return defaultValue;

    var arguments = new object[] { value, null };
    return ((bool) tryParseMethod.Invoke(null, arguments)) ? (TOutput) arguments[1] : defaultValue;
}

Этот метод расширения позволяет анализировать string как любой type, имеющий метод TryParse() а также позволяет указать значение по умолчанию, которое будет возвращаться в случае сбоя преобразования.

Это лучше, чем использовать троичный оператор с методом расширения, описанным выше, поскольку он выполняет преобразование только один раз. Это все еще использует отражение, хотя...

Примеры:

"123".ParseAs<int>(10);
"abc".ParseAs<int>(25);
"123,78".ParseAs<double>(10);
"abc".ParseAs<double>(107.4);
"2014-10-28".ParseAs<DateTime>(DateTime.MinValue);
"monday".ParseAs<DateTime>(DateTime.MinValue);

Выходы:

123
25
123,78
107,4
28.10.2014 00:00:00
01.01.0001 00:00:00
  • 3
    Я полагаю, что вы, возможно, изобрели один из самых неэффективных подходов, которые я когда-либо видел. Вы не только дважды анализируете строку (в случае ее разбора), но и вызываете функции отражения несколько раз, чтобы сделать это. И, в конце концов, вы даже не сохраняете нажатия клавиш, используя метод расширения.
  • 0
    Спасибо за то, что вы просто повторили то, что я написал сам со второго по последний абзац. Также, если вы берете мой последний пример во внимание, вы определенно сохраняете нажатия клавиш, используя этот метод расширения. Этот ответ не претендует на то, чтобы быть каким-то волшебным решением любой проблемы, это всего лишь пример кода. Используйте это, или не используйте это. Я думаю, что это удобно, когда используется правильно. И это включает в себя примеры как методов расширения, так и рефлексии, возможно, кто-то может извлечь из этого уроки.
Показать ещё 3 комментария
8

Вы можете использовать TryParse, чтобы определить, может ли строка быть проанализирована в целое число.

int i;
bool bNum = int.TryParse(str, out i);

Булев скажет вам, работает ли он или нет.

6

Double.TryParse

bool Double.TryParse(string s, out double result)
5

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

var numberString = "123";
int number;

int.TryParse(numberString , out number);

Обратите внимание, что TryParse возвращает bool, который вы можете использовать, чтобы проверить, удалось ли ваш синтаксический анализ.

2
public static bool IsNumeric(this string input)
{
    int n;
    if (!string.IsNullOrEmpty(input)) //.Replace('.',null).Replace(',',null)
    {
        foreach (var i in input)
        {
            if (!int.TryParse(i.ToString(), out n))
            {
                return false;
            }

        }
        return true;
    }
    return false;
}
2

Используйте эти методы расширения, чтобы четко различать проверку, является ли строка числовой, и содержит ли строка только 0-9 цифр.

public static class ExtensionMethods
{
    /// <summary>
    /// Returns true if string could represent a valid number, including decimals and local culture symbols
    /// </summary>
    public static bool IsNumeric(this string s)
    {
        decimal d;
        return decimal.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentCulture, out d);
    }

    /// <summary>
    /// Returns true only if string is wholy comprised of numerical digits
    /// </summary>
    public static bool IsNumbersOnly(this string s)
    {
        if (s == null || s == string.Empty)
            return false;

        foreach (char c in s)
        {
            if (c < '0' || c > '9') // Avoid using .IsDigit or .IsNumeric as they will return true for other characters
                return false;
        }

        return true;
    }
}
2

С помощью С# 7 вы можете вставить переменную out:

if(int.TryParse(str, out int v))
{
}
1

Лучшее гибкое решение со встроенной функцией.net called- char.IsDigit. Работает с неограниченными длинными номерами. Он вернет true, только если каждый символ представляет собой числовое число. Я использовал его много раз без проблем и с гораздо более простым решением, которое я когда-либо нашел. Я сделал пример метода. Он готов к использованию. Кроме того, я добавил валидацию для нулевого и пустого ввода. Таким образом, метод теперь полностью пуленепробиваемый

public static bool IsNumeric(string strNumber)
    {
        if (string.IsNullOrEmpty(strNumber))
        {
            return false;
        }
        else
        {
            int numberOfChar = strNumber.Count();
            if (numberOfChar > 0)
            {
                bool r = strNumber.All(char.IsDigit);
                return r;
            }
            else
            {
                return false;
            }
        }
    }
1

ОБНОВЛЕНИЕ Кунала Ноэля Ответ

stringTest.All(char.IsDigit);
// This returns true if all characters of the string are digits.

Но для этого случая у нас есть пустые строки, которые пройдут этот тест, так что вы можете:

if (!string.IsNullOrEmpty(stringTest) && stringTest.All(char.IsDigit)){
   // Do your logic here
}
1

Надеюсь, что это поможет

string myString = "abc";
double num;
bool isNumber = double.TryParse(myString , out num);

if isNumber 
{
//string is number
}
else
{
//string is not a number
}
0

Потяните ссылку на Visual Basic в свой проект и используйте свой метод Information.IsNumeric, такой как показано ниже, и сможете записывать как float, так и целые числа, в отличие от вышеприведенного ответа, который только ловит ints.

    // Using Microsoft.VisualBasic;

    var txt = "ABCDEFG";

    if (Information.IsNumeric(txt))
        Console.WriteLine ("Numeric");

IsNumeric("12.3"); // true
IsNumeric("1"); // true
IsNumeric("abc"); // false
  • 0
    Потенциальная проблема этого подхода заключается в том, что IsNumeric выполняет анализ строки символов. Таким образом, число типа 9999999999999999999999999999999999999999999999999999999999.99999999999 будет регистрироваться как True , даже если нет способа представить это число, используя стандартный числовой тип.
0
  • 0
    Вы могли бы хотя бы упомянуть название метода в своем ответе ...
  • 0
    имя метода указано!
-5
//To my knowledge I did this in a simple way
static void Main(string[] args)
{
    string a, b;
    int f1, f2, x, y;
    Console.WriteLine("Enter two inputs");
    a = Convert.ToString(Console.ReadLine());
    b = Console.ReadLine();
    f1 = find(a);
    f2 = find(b);

    if (f1 == 0 && f2 == 0)
    {
        x = Convert.ToInt32(a);
        y = Convert.ToInt32(b);
        Console.WriteLine("Two inputs r number \n so that addition of these text box is= " + (x + y).ToString());
    }
    else
        Console.WriteLine("One or two inputs r string \n so that concatenation of these text box is = " + (a + b));
    Console.ReadKey();
}

static int find(string s)
{
    string s1 = "";
    int f;
    for (int i = 0; i < s.Length; i++)
       for (int j = 0; j <= 9; j++)
       {
           string c = j.ToString();
           if (c[0] == s[i])
           {
               s1 += c[0];
           }
       }

    if (s == s1)
        f = 0;
    else
        f = 1;

    return f;
}
  • 1
    Четыре отрицательных голоса, но никто не сказал, почему? Я предполагаю, что это потому, что TryParse / Parse был бы лучшим вариантом, но не все, кто придет сюда, будут это знать.
  • 2
    Вы сделали это настолько сложным, что даже программист на С сказал бы: «Черт, должен быть более простой способ написать это»
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню