Tutorial :Regular expression for decimal number



Question:

I need to validate a textbox input and can only allow decimal inputs like: X,XXX (only one digit before decimal sign and a precision of 3).

I'm using C# and try this ^[0-9]+(\.[0-9]{1,2})?$?


Solution:1

^[0-9]([.,][0-9]{1,3})?$  

It allows:

0  1  1.2  1.02  1.003  1.030  1,2  1,23  1,234  

BUT NOT:

.1  ,1  12.1  12,1  1.  1,  1.2345  1,2345  


Solution:2

There is an alternative approach, which does not have I18n problems (allowing ',' or '.' but not both): Decimal.TryParse.

Just try converting, ignoring the value.

bool IsDecimalFormat(string input) {    Decimal dummy;    return Decimal.TryParse(input, out dummy);  }  

This is significantly faster than using a regular expression, see below.

(The overload of Decimal.TryParse can be used for finer control.)


Performance test results: Decimal.TryParse: 0.10277ms, Regex: 0.49143ms

Code (PerformanceHelper.Run is a helper than runs the delegate for passed iteration count and returns the average TimeSpan.):

using System;  using System.Text.RegularExpressions;  using DotNetUtils.Diagnostics;    class Program {      static private readonly string[] TestData = new string[] {          "10.0",          "10,0",          "0.1",          ".1",          "Snafu",          new string('x', 10000),          new string('2', 10000),          new string('0', 10000)      };        static void Main(string[] args) {          Action parser = () => {              int n = TestData.Length;              int count = 0;              for (int i = 0; i < n; ++i) {                  decimal dummy;                  count += Decimal.TryParse(TestData[i], out dummy) ? 1 : 0;              }          };          Regex decimalRegex = new Regex(@"^[0-9]([\.\,][0-9]{1,3})?$");          Action regex = () => {              int n = TestData.Length;              int count = 0;              for (int i = 0; i < n; ++i) {                  count += decimalRegex.IsMatch(TestData[i]) ? 1 : 0;              }          };            var paserTotal = 0.0;          var regexTotal = 0.0;          var runCount = 10;          for (int run = 1; run <= runCount; ++run) {              var parserTime = PerformanceHelper.Run(10000, parser);              var regexTime = PerformanceHelper.Run(10000, regex);                Console.WriteLine("Run #{2}: Decimal.TryParse: {0}ms, Regex: {1}ms",                                parserTime.TotalMilliseconds,                                 regexTime.TotalMilliseconds,                                run);              paserTotal += parserTime.TotalMilliseconds;              regexTotal += regexTime.TotalMilliseconds;          }            Console.WriteLine("Overall averages: Decimal.TryParse: {0}ms, Regex: {1}ms",                            paserTotal/runCount,                            regexTotal/runCount);      }  }  


Solution:3

\d{1}(\.\d{1,3})?    Match a single digit 0..9 «\d{1}»     Exactly 1 times «{1}»  Match the regular expression below and capture its match into backreference number 1 «(\.\d{1,3})?»     Between zero and one times, as many times as possible, giving back as needed (greedy) «?»     Match the character “.” literally «\.»     Match a single digit 0..9 «\d{1,3}»        Between one and 3 times, as many times as possible, giving back as needed (greedy) «{1,3}»      Created with RegexBuddy  

Matches:
1
1.2
1.23
1.234


Solution:4

In general, i.e. unlimited decimal places:

^-?(([1-9]\d*)|0)(.0*[1-9](0*[1-9])*)?$


Solution:5

I just found TryParse() has an issue that it accounts for thousands seperator. Example in En-US, 10,36.00 is ok. I had a specific scenario where the thousands seperator should not be considered and hence regex \d(\.\d) turned out to be the best bet. Of course had to keep the decimal char variable for different locales.


Solution:6

In .NET, I recommend to dynamically build the regular expression with the decimal separator of the current cultural context:

using System.Globalization;    ...    NumberFormatInfo nfi = NumberFormatInfo.CurrentInfo;  Regex re = new Regex("^(?\\d+("                      + Regex.Escape(nfi.CurrencyDecimalSeparator)                      + "\\d{1,2}))$");  

You might want to pimp the regexp by allowing 1000er separators the same way as the decimal separator.


Solution:7

As I tussled with this, TryParse in 3.5 does have NumberStyles: The following code should also do the trick without Regex to ignore thousands seperator.

double.TryParse(length, NumberStyles.AllowDecimalPoint,CultureInfo.CurrentUICulture, out lengthD))  

Not relevant to the original question asked but confirming that TryParse() indeed is a good option.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »