views:

285

answers:

2

Hi

I'm after a regular expression that matches a UK Currency (ie. £13.00, £9,999.99 and £12,333,333.02), but does not allow negative (-£2.17) or zero values (£0.00 or 0).

I've tried to create one myself, but I've got in a right muddle!

Any help greatfully received.

Thanks!

+3  A: 

This'll do it (well mostly...)

/^£?[1-9]{1,3}(,\d{3})*(\.\d{2})?$/

Leverages the ^ and $ to make sure no negative or other character is in the string, and assumes that commas will be used. The pound symbol, and pence are optional.

edit: realised you said non-zero so replaced the first \d with [1-9]

Update: it's been pointed out the above won't match £0.01. The below improvement will but now there's a level of complexity where it may quite possibly be better to test /[1-9]/ first and then the above - haven't benchmarked it.

/^£?(([1-9]{1,3}(,\d{3})*(\.\d{2})?)|(0\.[1-9]\d)|(0\.0[1-9]))$/

Brief explanation:

  • Match beginning of string followed by optional "£"
  • Then match either:
    • a >£1 amount with potential for comma separated groupings and optional pence
    • OR a <£1 >=£0.10 amount
    • OR a <=£0.09 amount
  • Then match end of line

The more fractions of pence (zero in the above) you require adding to the regex the less efficient it becomes.

annakata
What about 0.50? That won't match...
Tim Pietzcker
@Tim - Well spotted. Corrected.
annakata
Brilliant. Thanks - it would have taken me ages to come up with that.
Sniffer
A: 

You could just make two passes:

/^£\d{1,3}(,\d{3})*(\.\d{2})?$/

to validate the format, and

/[1-9]/

to ensure that at least one digit is non-zero.

This is less efficient than doing it in one pass, of course (thanks, annakata, for the benchmark information), but for a first implementation, just "saying what you want" can significantly reduce developing time.

Svante
I benchmarked it - you'd have to have 100K's of failed matches before doing a precheck becomes significantly cheaper. It's not worth the logic/readability issues.
annakata