4

I have the following regular expression:

^[-+]?[\d{0,3},?\d{3}]*\.?\d+$

I am trying to support numbers of the following formats:

  • 1
  • -1
  • -1.00
  • 100,000

I am not concerned about scientific notation but my users may or may not enter in commas. The problem I am having is that the expression is matching:

  • 100,
  • 100,00

How can I have the expression indicate that if there is a comma then there must be three characters after it.

8
  • 2
    If you are taking the numeric input for use as actual numbers, can't you just strip out the commas? Commented Mar 4, 2010 at 18:26
  • That will work, but he may want values like 10,00 to be actually invalid and to enforce that. Commented Mar 4, 2010 at 18:33
  • I can't strip out the commas because we want to display them to the user as they enter them but we will need to perform calculations @ the server. Commented Mar 4, 2010 at 18:38
  • @Josh, then store the value twice in the database. Once as entered as a string, and once as the real value as a decimal/float/etc. Then you can display what was entered AND perform calculations on the real value Commented Mar 4, 2010 at 18:41
  • 2
    @Josh: It makes sense to validate on the client side. @Chad: It doesn't make sense to store the value twice in the DB when simple formatting can present the single stored value properly in all cases. Commented Mar 4, 2010 at 18:50

5 Answers 5

6

Try this regular expression:

/^[-+]?(?:\d*|\d{1,3}(?:,\d{3})*)(?:\.\d+)?$/
Sign up to request clarification or add additional context in comments.

5 Comments

What's the : character do I don't see it my reference.
@Josh: (?:…) is a non-capturing grouping that’s match can not be referenced.
This works for all test cases I've thrown at it except for .25 which we change the first \d+ to \d*.
@Josh: Yes, using \d* instead of \d+ would match .25.
Ok I edited your answer to reflect \d*. Thank you for the help!
1

Try this

^([-+]?\d(?:(,\d{3})|(\d*))+\d*)?\.?\d*$ 

SUCCESSES

0
1
-1
-1.00
100,000
100.0
1,111,111
.25

FAILURES

100.0.
100.0,
asdf100.0
100,
1,11,111
,111,111

2 Comments

That's an odd one. You've build it to accept "100,0000", "10000,000", etc. The only real requirement seems to be that, if there's a comma, then the next 3 characters must be digits -- which is literally what the OP asked for, but probably not what he wanted. :-)
@Ken: Wow great example of how hard it can be to accuratley specify a simple problem. Probally should have said you need to ensure that there is 1-3 digits before a comma and 3 digits after a comma. I think that covers it.
1

As Robert Harvey indicated, if all you're concerned about is capturing numeric values to use in your program, you can just strip out the commas and all will be well.

However, assuming this is a formatting question (that is, you're checking keystrokes and only allowing valid input, or reformatting the input to be a valid numeric value), then you could try something like this:

EDIT: ^[+-]?\d{1,3}(,\d{3})*(\.\d+)?$

What this does is allow any number of sets of a comma and 3 digits, followed by zero or one set of a dot followed by one or more digits.

5 Comments

That last edit was because I tested the regex, fixed the errors, and it does in fact match all the test cases I could think of.
[boast] I'd also point out that my regex is, IMO, one of the most straight-forward yet presented. ;D [/boast]
It is the easiest to read hence my +1, I'm not sure what the benefit of using a non-capturing vs capturing group which is one of the key diffs btw yours and Gumbo's
There's no difference except that his version is non-capturing. Mine is easier to read; I don't see the need to add more characters to complicate things, but if you like, feel free to add the ?: inside each group.
fyi, it fails with ",111". By "fails", I mean passes, and shouldn't.
0

You've put your "count" qualifiers inside square brackets, which doesn't make sense (well it makes sense, syntactically, but it's not doing what you think it's doing).

Comments

0

Why not just whack all commas and then test?

g=oldstring.replace(',','');
g=g.replace('.','');//may as well do dots too
if (! g.match('/^[0-9]*[0-9]$/'))
    alert("Bummerific");

Additionally if you're going to allow commas then you shouldn't make them place commas every 3 digits. International users use commas to separate decimal place. In which case if you wanna be pedantic then this regex will probably work

/^[0-9][0-9,.]*[0-9]$/

Good Luck!

1 Comment

Because I can't assume that 100,54.99 wasn't a typo. And let's say hypothetically we are dealing with money here well that could be a very costly typo. As for international users, I can't wait to have enough customers that we start targeting international users and at that point. I will be on a beach sipping my pina-colada:) (Or we can just localize the expression when that day comes).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.