John Smith
John Smith

Reputation: 233

Validate float number using RegEx in C#

I am trying to make a Numeric only TextBox in WPF and I have this code for it:

void NumericTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    e.Handled = !IsValidInput(e.Text);
}

private bool IsValidInput(string p)
{
    switch (this.Type)
    {
        case NumericTextBoxType.Float:
            return Regex.Match(p, "^[0-9]*[.][0-9]*$").Success;
        case NumericTextBoxType.Integer:                    
        default:
            return Regex.Match(p, "^[0-9]*$").Success;                    
    }
}

// And also this!
public enum NumericTextBoxType
{
    Integer = 0, 
    Float = 1
}

When I set the type to Integer, it works well, but for Float, it does not.

I can use so many NumericTextBox controls out there, but I was wondering why this one is not working?

Upvotes: 11

Views: 42797

Answers (6)

Dmitrii Lobanov
Dmitrii Lobanov

Reputation: 4977

I urge you to use Double.TryParse() method instead of regex validation. Using TryParse() let your application to be a bit more universal in terms of culture. When current culture changes, TryParse() will parse with no problem. Also TryParse() methods believed to have no bugs as they were tested by .net community.

But in case of regex your should change your validation expression hence it could be no relevant to new culture.

You can rewrite code like this:

private bool IsValidInput(string p)
{
    switch (this.Type)
    {
        case NumericTextBoxType.Float:
            double doubleResult;
            return double.TryParse(p, out doubleResult);
        case NumericTextBoxType.Integer:                    
        default:
            int intResult;
            return int.TryParse(p, out intResult);
    }
}

You can even add your own extension methods to make parsing part more elegant.

public static double? TryParseInt(this string source)
{
    double result;
    return double.TryParse(source, out result) ? result : (double?)null;
}

// usage
bool ok = source.TryParseInt().HasValue;

Upvotes: 13

Ananda
Ananda

Reputation: 918

This is a code I came up by mixing replies from @Andrew Cooper and @Ramesh. Added the dictionary code so any body thinking of testing the code can run as many test cases the easy way.

//greater than or equal to zero floating point numbers
Regex floating = new Regex(@"^[0-9]*(?:\.[0-9]+)?$");
        Dictionary<string, bool> test_cases = new Dictionary<string, bool>();
        test_cases.Add("a", floating.IsMatch("a"));
        test_cases.Add("a.3", floating.IsMatch("a.3"));
        test_cases.Add("0", floating.IsMatch("0"));
        test_cases.Add("-0", floating.IsMatch("-0"));
        test_cases.Add("-1", floating.IsMatch("-1"));
        test_cases.Add("0.1", floating.IsMatch("0.1"));
        test_cases.Add("0.ab", floating.IsMatch("0.ab"));

        test_cases.Add("12", floating.IsMatch("12"));
        test_cases.Add(".3", floating.IsMatch(".3"));
        test_cases.Add("12.3", floating.IsMatch("12.3"));
        test_cases.Add("12.3.4", floating.IsMatch("12.3.4"));
        test_cases.Add(".", floating.IsMatch("."));

        test_cases.Add("0.3", floating.IsMatch("0.3"));
        test_cases.Add("12.31252563", floating.IsMatch("12.31252563"));
        test_cases.Add("-12.31252563", floating.IsMatch("-12.31252563"));

        foreach (KeyValuePair<string, bool> pair in test_cases)
        {
            Console.WriteLine(pair.Key.ToString() + "  -  " + pair.Value);
        }

Upvotes: 0

Berezh
Berezh

Reputation: 937

[-+]?\d+(.\d+)?

The most simple regex for float. It it doesn't match the cases '123.' or '.123'.

Also, you should look on context culture:

CultureInfo ci = CultureInfo.CurrentCulture;
var decimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
var floatRegex = string.Format(@"[-+]?\d+({0}\d+)?", decimalSeparator);

Upvotes: 2

Ramesh
Ramesh

Reputation: 31

I tried the solution approved above, found that it will fail if user enters a dot only @"^[0-9]*(?:\.[0-9]*)?$".

So, I modified it to:

@"^[0-9]*(?:\.[0-9]+)?$"

Upvotes: 2

Rob Smyth
Rob Smyth

Reputation: 1858

Check out the TryParse static methods you will find on double, float, and int.

They return true if the string can be parsed (by the Parse method).

Upvotes: 4

Andrew Cooper
Andrew Cooper

Reputation: 32576

Try this:

@"^[0-9]*(?:\.[0-9]*)?$"

You need to escape the period. And making the period and decimal part optional is probably a good idea.

If you need to handle negative values you can add -? before the first [0-9] in each pattern.

Update

Tested as follows:

var regex = new Regex(@"^[0-9]*(?:\.[0-9]*)?$");
Console.WriteLine(new bool[] {regex.IsMatch("blah"),
                              regex.IsMatch("12"),
                              regex.IsMatch(".3"),
                              regex.IsMatch("12.3"),
                              regex.IsMatch("12.3.4")});

results in

False 
True 
True 
True 
False 

Upvotes: 29

Related Questions