8

What is a regular expression suitable for C# that'll validate a number if it matches the following?

 $1,000,000.150
 $10000000.199
 $10000 
 1,000,000.150
 100000.123
 10000

Or the negative equivalents?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nailitdown
  • 7,868
  • 11
  • 36
  • 37
  • Do you need to use RegEx? Is the number you're looking for embedded within more text, or do you just want to be able to parse a string that might be in one of the above formats? – Matt Hamilton Mar 06 '09 at 06:31
  • since when does valid currency has 3 digits after the period? – csmba Mar 06 '09 at 06:34
  • @csmba Why not? A cost per kg of a product you sell in tonnes might go to three decimal places. – Matt Hamilton Mar 06 '09 at 06:36
  • I'm using a third party control with limited validation options - basically "number". this has no option for currency, so i need to use a regex. I can handle the various formats on the back end, so it'd be nice not to throw an error at the user when they input a currency value. – nailitdown Mar 06 '09 at 06:36
  • @csamba - exactly as matt says, these guys deal in large numbers, large quantities, 3 decimal places. – nailitdown Mar 06 '09 at 06:36
  • @[more than two digits after the period]: Have a look at the exchange rates between currencies. They usually have four decimal places. And it would be kind of bad if that wouldn't be a valid value ;) – OregonGhost Mar 06 '09 at 07:41
  • I understand that other *currencies* do not exist, right? the world is spinning around dollar alone... ;) – poncha Jun 18 '12 at 07:25

8 Answers8

14

You can use csmba's regex if you make one slight modification to it.

^\$?(\d{1,3},?(\d{3},?)*\d{3}(.\d{0,3})?|\d{1,3}(.\d{2})?)$
gregwhitaker
  • 13,124
  • 7
  • 69
  • 78
5

I think ssg is right. It's not a really good use of Regex, especially if your software has to deal with non-US centric data entry.

For instance, if the currency symbol is the Euro, or the Japanese Yen or the British Pound any of the other dozen currency symbols out there?

What about number formatting rules?

In the US you would enter 1,000,000.00 but in France, this should be 1.000.000,00. Other countries allow spacing between digit-grouping...

If you use a straight Regex without taking the Culture into account, then you're never going to validate successfully unless you're 100% sure your software will never ever be used in a non-US centric context.

Renaud Bompuis
  • 16,596
  • 4
  • 56
  • 86
3
^\$?(\d{1,3},?(\d{3},?)*\d{3}(\.\d{1,3})?|\d{1,3}(\.\d{2})?)$
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
csmba
  • 4,053
  • 3
  • 32
  • 42
2

I think I've found a problem with ssg's solution (or perhaps an MS bug!).

Running this:

float.TryParse("0,2",NumberStyles.Currency, CultureInfo.GetCultureInfo("en-US"), out num)

Returns true. Surely "0,2" isn't a valid currency value?

Ben Power
  • 1,786
  • 5
  • 27
  • 35
  • that would be .20 in France, mexico, spain, or any other latin derived country. See the comments above on international formats. Funny, however, that in specifying US you are still getting true. That would be a bug if it is repeatable. – Zack Jannsen Aug 07 '12 at 23:17
  • It does indeed appear to be an MS bug. Here are some of the combinations I tried in the Immediate Window: float.TryParse("0,2",NumberStyles.Currency, CultureInfo.GetCultureInfo("en-US"), out num) RETURNS true float.TryParse("0,2",NumberStyles.Currency, CultureInfo.GetCultureInfo("en-AU"), out num) RETURNS true float.TryParse("0..2",NumberStyles.Currency, CultureInfo.GetCultureInfo("en-AU"), out num) RETURNS false float.TryParse("0.2",NumberStyles.Currency, CultureInfo.GetCultureInfo("en-AU"), out num) RETURNS true – Ben Power Aug 17 '12 at 01:09
  • I don't think it is a bug. The comma is merely a grouping separator, not a radix. It's utterly logical that "0,2" is successfully parsed as 2. Likewise, "0,2.98" would be parsed as: 2.98 – uygar.raf Mar 01 '23 at 20:59
1

Be careful with floats. Eventually you will hit a case such as 0.01 represented as 0.00999999. Strings or integers are better to use.

Brian Carlton
  • 7,545
  • 5
  • 38
  • 47
0

This regular Expression works for me:

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

with switch

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

it works for

  • $1,000,000.150
  • 10000000.199
  • $10000
  • 1,000,000.150
  • 100000.123
  • 10000
0

Try this one. It may need some fine tuning to only allow for a single decimal point, but it does match your test cases. I hope this helps.

[$\d,.]+
James
  • 12,636
  • 12
  • 67
  • 104
0

Use this regular expression for US currency \$(\d)*\d Matches $300,$12900 Non-Match $12900.00