105

What is the most efficient way of testing an input string whether it contains a numeric value (or conversely Not A Number)? I guess I can use Double.Parse or a regex (see below) but I was wondering if there is some built in way to do this, such as javascript's NaN() or IsNumeric() (was that VB, I can't remember?).

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}
Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
johnc
  • 39,385
  • 37
  • 101
  • 139
  • 1
    Possible duplicate of [How do I identify if a string is a number?](http://stackoverflow.com/questions/894263/how-do-i-identify-if-a-string-is-a-number) – Michael Freidgeim May 18 '17 at 06:15

16 Answers16

181

This doesn't have the regex overhead

double myNum = 0;
String testVar = "Not A Number";

if (Double.TryParse(testVar, out myNum)) {
  // it is a number
} else {
  // it is not a number
}

Incidentally, all of the standard data types, with the glaring exception of GUIDs, support TryParse.

update
secretwep brought up that the value "2345," will pass the above test as a number. However, if you need to ensure that all of the characters within the string are digits, then another approach should be taken.

example 1:

public Boolean IsNumber(String s) {
  Boolean value = true;
  foreach(Char c in s.ToCharArray()) {
    value = value && Char.IsDigit(c);
  }

  return value;
}

or if you want to be a little more fancy

public Boolean IsNumber(String value) {
  return value.All(Char.IsDigit);
}

update 2 ( from @stackonfire to deal with null or empty strings)

public Boolean IsNumber(String s) { 
    Boolean value = true; 
    if (s == String.Empty || s == null) { 
        value=false; 
    } else { 
        foreach(Char c in s.ToCharArray()) { 
            value = value && Char.IsDigit(c); 
        } 
    } return value; 
}
NotMe
  • 87,343
  • 27
  • 171
  • 245
  • If needed, You can wrap the above code into a more helpful utility method like public static bool IsInteger(string sMaybeANumber) – Gishu Jan 13 '09 at 04:51
  • @Gishu: You are right if all you care about is whether the number can convert. – NotMe Jan 16 '09 at 15:25
  • 2
    The only issue with this is the `Number` object in Javascript is a float or integer, so changing to double.TryParse would be a more exact equivalent – Chris S Nov 09 '09 at 14:27
  • 7
    You might want to be careful with this as the strings "NaN" and "Infinity" parse to a `double`, but many would consider them to be not numeric. – Mike Zboray Dec 01 '12 at 22:22
  • Example 1, the first example, will return true if given an empty string. – Dave Kelly Jun 28 '19 at 11:52
  • 1
    A corrected Example 1 to deal with null or empty strings, which were otherwise causing IsNumber to erroneously return true: `public Boolean IsNumber(String s) { Boolean value = true; if (s == String.Empty || s == null) { value=false; } else { foreach(Char c in s.ToCharArray()) { value = value && Char.IsDigit(c); } } return value; }` – stackonfire Oct 30 '19 at 18:09
  • @stackonfire: your update looks good, I included it in the post. – NotMe Oct 31 '19 at 14:19
40

I prefer something like this, it lets you decide what NumberStyle to test for.

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}
Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
20

In addition to the previous correct answers it is probably worth pointing out that "Not a Number" (NaN) in its general usage is not equivalent to a string that cannot be evaluated as a numeric value. NaN is usually understood as a numeric value used to represent the result of an "impossible" calculation - where the result is undefined. In this respect I would say the Javascript usage is slightly misleading. In C# NaN is defined as a property of the single and double numeric types and is used to refer explicitly to the result of diving zero by zero. Other languages use it to represent different "impossible" values.

Stu Mackellar
  • 11,510
  • 1
  • 38
  • 59
11

I know this has been answered in many different ways, with extensions and lambda examples, but a combination of both for the simplest solution.

public static bool IsNumeric(this String s)
{
    return s.All(Char.IsDigit);
}

or if you are using Visual Studio 2015 (C# 6.0 or greater) then

public static bool IsNumeric(this String s) => s.All(Char.IsDigit);

Awesome C#6 on one line. Of course this is limited because it just tests for only numeric characters.

To use, just have a string and call the method on it, such as:

bool IsaNumber = "123456".IsNumeric();
Paul Bartlett
  • 673
  • 1
  • 9
  • 14
  • 1
    For users unfamiliar with [extension methods](https://msdn.microsoft.com/en-us/library/bb383977.aspx), it might be beneficial to include some more information (or at least the surrounding static class to provide a more complete example). – johnnyRose Jan 21 '16 at 21:23
  • I don't like this solution because it will return false for numbers with a decimal. It could be useful for integers, but if that's what you want to use it for the method should be renamed IsInteger – SendETHToThisAddress Jun 01 '20 at 23:31
5

I like the extension method, but don't like throwing exceptions if possible. I opted for an extension method taking the best of 2 answers here.

    /// <summary>
    /// Extension method that works out if a string is numeric or not
    /// </summary>
    /// <param name="str">string that may be a number</param>
    /// <returns>true if numeric, false if not</returns>
    public static bool IsNumeric(this String str)
    {
        double myNum = 0;
        if (Double.TryParse(str, out myNum))
        {
            return true;
        }
        return false;
    }
NER1808
  • 1,829
  • 2
  • 33
  • 45
5

Yeah, IsNumeric is VB. Usually people use the TryParse() method, though it is a bit clunky. As you suggested, you can always write your own.

int i;
if (int.TryParse(string, out i))
{

}
Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
Ed S.
  • 122,712
  • 22
  • 185
  • 265
4

Simple extension:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}
shA.t
  • 16,580
  • 5
  • 54
  • 111
MrSiir
  • 61
  • 1
  • 2
4

You can still use the Visual Basic function in C#. The only thing you have to do is just follow my instructions shown below:

  1. Add the reference to the Visual Basic Library by right clicking on your project and selecting "Add Reference":

enter image description here

  1. Then import it in your class as shown below:

    using Microsoft.VisualBasic;

  2. Next use it wherever you want as shown below:

                if (!Information.IsNumeric(softwareVersion))
            {
                throw new DataException(string.Format("[{0}] is an invalid App Version!  Only numeric values are supported at this time.", softwareVersion));
            }
    

Hope, this helps and good luck!

Vincy
  • 1,078
  • 1
  • 9
  • 16
  • 2
    While I would not recommend this method, it *is* a correct answer. Not sure why it was downvoted, and since it was not explained why either, I up-voted to counteract it :-) – Abacus Aug 31 '15 at 19:08
4

VB has the IsNumeric function. You could reference Microsoft.VisualBasic.dll and use it.

Chad
  • 1,531
  • 3
  • 20
  • 46
shahkalpesh
  • 33,172
  • 3
  • 63
  • 88
  • Can you only get that VB method in > 2.0 versions of .net? – Ed S. Jan 13 '09 at 03:38
  • @ChuckD: That is subjective. Do you refer external libraries that deal with json or write it all to parse json yourself? – shahkalpesh Jul 03 '18 at 14:01
  • @ChuckD: Spare me the drivel and explain why it is crap. For me, it is just another dll that contains some useful classes/functions. – shahkalpesh Jul 05 '18 at 14:06
  • @ChuckD I think you're being unreasonable here. The function does the job, it's easy to import in and it's not that big of a deal. – Bugs Jul 05 '18 at 14:10
  • @JoelCoehoorn: Do you think it is a bad idea to use microsoft.visualbasic.dll and use some of the functions provided in it whether or not an equivalent function can be used from c# without referring another dll? – shahkalpesh Jul 05 '18 at 14:12
  • Is numeric is a single line extension to write in c#. Why would you drag in a bloated, legacy dll which i'm guessing also includes many COM interop refs and extra overhead. You include things like Json.Net because they're purposeful and don't drag in extra dependencies. Try dragging in VisualBasic.dll and get your stuff ported to Mono. Nobody should be teaching you these bad habits. – Chuck D Jul 05 '18 at 14:16
  • @ChuckD: You are expanding it to Mono, which is not the question. If it were Mono, things would be different. How is visualbasic.dll legacy/bloated? How does calling Isnumeric involve com interop? – shahkalpesh Jul 05 '18 at 14:20
  • @ChuckD: I dont know why MS folks write crap(?) like [this](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/namespaces/how-to-use-the-my-namespace) – shahkalpesh Jul 05 '18 at 14:26
  • @shahkalpesh - This isn't the place to drag out a discussion of common sense. Please continue to code the way you see as logical and i'll continue to do the same. If you look at the direction of .Net Core, you will understand my issues. Also, look at the widely accepted answer and take some advice instead of questioning someone's feedback. – Chuck D Jul 05 '18 at 14:29
  • 1
    @ChuckD you may want to start with constructive criticism instead of starting with _Importing VisualBasic.dll for IsNumeric should get you fired!_ which is clearly going to get someones back up. The answer was back in '09 and even now stands to be useful to some people. – Bugs Jul 05 '18 at 14:34
  • My apologies, comments have been cleaned up. If you chose to argue your proposed answer over the accepted answer then you're not using the site correctly. – Chuck D Jul 05 '18 at 15:14
3
public static bool IsNumeric(string anyString)
{
    if (anyString == null)
    {
        anyString = "";
    }

    if (anyString.Length > 0)
    {
        double dummyOut = new double();
        System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-US", true);
        return Double.TryParse(anyString, System.Globalization.NumberStyles.Any, cultureInfo.NumberFormat, out dummyOut);
    }
    else
    {
        return false;
    }
}
Peter Jacoby
  • 2,406
  • 25
  • 26
Mnaouar
  • 31
  • 1
3

Maybe this is a C# 3 feature, but you could use double.NaN.

Chad
  • 1,531
  • 3
  • 20
  • 46
kenny
  • 21,522
  • 8
  • 49
  • 87
2

I was using Chris Lively's snippet (selected answer) encapsulated in a bool function like Gishu's suggestion for a year or two. I used it to make sure certain query strings were only numeric before proceeding with further processing. I started getting some errant querystrings that the marked answer was not handling, specifically, whenever a comma was passed after a number like "3645," (returned true). This is the resulting mod:

   static public bool IsNumeric(string s)
   {
      double myNum = 0;
      if (Double.TryParse(s, out myNum))
      {
         if (s.Contains(",")) return false;
         return true;
      }
      else
      {
         return false;
      }
   }
secretwep
  • 706
  • 1
  • 12
  • 28
  • +1 for being interesting. I guess it's more of a usage question. In other words, if you just want to make sure the value can be converted to a number without throwing an error then my original answer is good. However, if you are more concerned that all of the characters within the string are actually digits then a completely different approach is needed – NotMe Jun 07 '13 at 20:40
  • `Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)` – Sam Harwell Jun 07 '13 at 21:24
2

Actually, Double.NaN is supported in all .NET versions 2.0 and greater.

CoolBeans
  • 20,654
  • 10
  • 86
  • 101
Madcat
  • 21
  • 1
1

This is a modified version of the solution proposed by Mr Siir. I find that adding an extension method is the best solution for reuse and simplicity in the calling method.

public static bool IsNumeric(this String s)
{
    try { double.Parse(s); return true; }
    catch (Exception) { return false; }
}

I modified the method body to fit on 2 lines and removed the unnecessary .ToString() implementation. For those not familiar with extension methods here is how to implement:

Create a class file called ExtensionMethods. Paste in this code:

using System;
using System.Collections.Generic;
using System.Text;

namespace YourNameSpaceHere
{
    public static class ExtensionMethods
    {
        public static bool IsNumeric(this String s)
        {
            try { double.Parse(s); return true; }
            catch (Exception) { return false; }
        }
    }
}

Replace YourNameSpaceHere with your actual NameSpace. Save changes. Now you can use the extension method anywhere in your app:

bool validInput = stringVariable.IsNumeric();

Note: this method will return true for integers and decimals, but will return false if the string contains a comma. If you want to accept input with commas or symbols like "$" I would suggest implementing a method to remove those characters first then test if IsNumeric.

SendETHToThisAddress
  • 2,756
  • 7
  • 29
  • 54
0

I have a slightly different version which returns the number. I would guess that in most cases after testing the string you would want to use the number.

public bool IsNumeric(string numericString, out Double numericValue)
{
    if (Double.TryParse(numericString, out numericValue))
        return true;
    else
        return false;
}
Keith Aymar
  • 876
  • 7
  • 10
0

If you don't want the overhead of adding the Microsoft.VisualBasic library just for isNumeric, here's the code reverse engineered:

public bool IsNumeric(string s)
{
    if (s == null) return false;

    int state = 0; // state 0 = before number, state 1 = during number, state 2 = after number
    bool hasdigits = false;
    bool hasdollar = false;
    bool hasperiod = false;
    bool hasplusminus = false;
    bool hasparens = false;
    bool inparens = false;

    for (var i = 0; i <= s.Length - 1; i++)
    {
        switch (s[i])
        {
            case char n when (n >= '0' && n <= '9'):
                    if (state == 2) return false; // no more numbers at the end (i.e. "1 2" is not valid)

                    if (state == 0) state = 1; // begin number state
                    hasdigits = true;
                    break;

            case '-':
            case '+':
                    // a plus/minus is allowed almost anywhere, but only one, and you cannot combine it with parenthesis
                    if (hasplusminus || hasparens) return false;

                    if (state == 1) state = 2; // exit number state (i.e. "1-" is valid but 1-1 is not)
                    hasplusminus = true;
                    break;

            case ' ':
            case '\t':
            case '\r':
            case '\n':
                    // don't allow any spaces after parenthesis/plus/minus, unless there's a $
                    if (state == 0 && (hasparens || (hasplusminus && !hasdollar))) return false;
                    if (state == 1) state = 2; // exit number state
                    break;

            case ',':
                    // do not allow commas unless in the middle of the number, and not after a decimal
                    if (state != 1 || hasperiod) return false;
                    break;

            case '.':
                    // only allow one period in the number
                    if (hasperiod || state == 2) return false;

                    if (state == 0) state = 1; // begin number state
                    hasperiod = true;
                    break;

            case '$':
                    // dollar symbol allowed anywhere, but only one
                    if (hasdollar) return false;

                    if (state == 1) state = 2; // exit number state (i.e. "1$" is valid but "1$1" is not)
                    hasdollar = true;
                    break;

            case '(':
                    // only allow one parens at the beginning, and cannot combine with plus/minus
                    if (state != 0 || hasparens || hasplusminus) return false;
                    hasparens = true;
                    inparens = true;
                    break;

            case ')':
                    if (state == 1 && inparens) state = 2; // exit number state
                    if (state != 2 || !inparens) return false; // invalid end parens
                    inparens = false; // end parens mode
                    break;

            default:
                    // oh oh, we hit a bad character
                    return false;
        }
    }

    // must have at leats one digit, and cannot have imbalanced parenthesis
    if (!hasdigits || inparens) return false;

    // if we got all the way to here...
    return true;
}
Brain2000
  • 4,655
  • 2
  • 27
  • 35