2

I'm looking for a regular expression that would validate a non-negative decimal (.NET type), i.e. if a non-negative value can be parsed using decimal.Parse(...), it should be considered valid. Otherwise invalid.

I'm okay if it fails the 28-29 significant digits validation - relying on user's sanity here - and then we have another validation layer that would catch it anyway.

Here is what I came up with:

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

Problem is that it rejects 1. which is a valid number (you can verify from the immediate window in VS). Could be other edge cases I did not test. Please advise.

P.S. I included ASP.NET and C# tags because this is for a web application written in C#, in which this regular expression is passed to a 3rd party component, which then works on the client (i.e. JS), so I cannot easily put custom code there (i.e. decimal.TryParse or smth like that).

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • `decimal.Parse` also accepts a leading sign. `"+1"` is a non-negative value that can be parsed. So is `"-0"`, even. `decimal.Parse` also accepts thousands separators: `"1,000"` can be parsed. `decimal.Parse` is culture-sensitive, so `.` shouldn't be hard-coded unless the culture is as well. `decimal.Parse` accepts whitespace. `" 100 "` can be parsed. There's probably more that I missed. –  Jul 22 '16 at 20:19
  • @hvd, yes I understand, thank you for mentioning those edge cases. I don't seek to be 100% perfect, just trying to cover 99.9% of test cases. There is also training to ensure that people don't go crazy on the UI. I'm sure it's always possible to break any program, if you really wanted to. – Victor Zakharov Jul 22 '16 at 20:23
  • @hvd, btw +1 test case is handled by the accepted answer. – Victor Zakharov Jul 22 '16 at 20:23
  • 1
    As long as you're aware of those edge cases and make a conscious decision not to support them, that's just fine. As long as you accept only a strict subset of what `decimal.Parse` accepts, it should be impossible to slip something by that then breaks your application. –  Jul 22 '16 at 20:29

1 Answers1

3

You can use this regex based on a negative lookahead to avoid matching single dot:

^(?!\D+$)\+?\d*?(?:\.\d*)?$
  • (?!\D+$) is negative lookahead to assert failure when input is non digit characters
  • ?:\.\d*)? allows for matching 123. type of number.

RegEx Demo 1

RegEx Demo 2

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Thanks - basic test cases seem to work fine. Could you please also add support for leading zeroes, like 001, and for cases when plus sign is explicitly specified, like +100 ? – Victor Zakharov Jul 22 '16 at 19:55
  • 1
    Correction - it accepts a bare + sign, which obviously is not a number. – Victor Zakharov Jul 22 '16 at 20:03
  • Yes use: [`^(?!\D+$)\+?\d*?(?:\.\d*)?$`](https://regex101.com/r/iB1hM8/3) – anubhava Jul 22 '16 at 20:07
  • 1
    Ok, perfect. Accepting - please don't forget to update your answer with latest regex and link to regex101.com - it really helps validate common edge cases. – Victor Zakharov Jul 22 '16 at 20:10
  • 1
    When testing .NET regexes, it is best to test at .NET dedicated testers. Regex101 does not support .NET syntax. Note that in .NET regex, `\d` does not equal `[0-9]` (see [this thread](http://stackoverflow.com/a/273144/3832970)). Do not forget to use `RegexOptions.ECMAScript` flag to make `\d` match the same digits as in JavaScript. – Wiktor Stribiżew Jul 22 '16 at 20:25
  • Fair point Wiktor. I thought http://www.regexplanet.com/ is .NET compliant regex tester that I had in my first demo – anubhava Jul 22 '16 at 21:13