简体   繁体   中英

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?

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 

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;

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).

[-+]?\\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);

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]+)?$"

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);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM