Nicke Manarin
Nicke Manarin

Reputation: 3358

Regex for decimals with maximum length

I'm not sure if this is possible with regex. I'll try to use regex, but if not possible I'll switch to a double validation.

My database (postgresql) accepts decimal as 15,6 (Maximum of 15 digits with a maximum of 6 decimals), so if I have 10 integer digits, I can have 5 decimals digits. The decimal separator is ignored.

I currently have this regex (Comma is the decimal separator):

^\d{1,15}(\,\d{1,6})?$

It does not verify the total length, only the numbers to the left. But since the user can also type dots (thousands separator), I have this monster:

^((\d+)|(\d{1,3}(\.\d{3})+)|(\d{1,3}(\.\d{3})(\,\d{3})+))((\,\d{4})|(\,\d{3})|(\,\d{2})|(\,\d{1})|(\,))?$

This one does not accept more than 3 decimals. I can edit this one to accept 6 decimais, but I still can't validate the total length.

Is it possible to verify the total length of the number? Ignoring the dots and comma.

The regex should accept:

1234567890,123456

1.234.567.890,123456

And of course any other middle values:

1.234,12, 1,0, 1...

Upvotes: 9

Views: 13264

Answers (4)

Danny Mora
Danny Mora

Reputation: 21

^(\d{0,15})([\.\,]\d{0,6})?$
  • Group 1:
    any number with max length = 15
  • group 2:
    any number with max length of two, preceded by , or .

Upvotes: 0

Chrono
Chrono

Reputation: 1473

Just throwing this out as an alternative. In my opinion you shouldn't use a Regex in this case. Why? Because the Regex that will actually match the question won't be easy to understand.

Much simpler solutions exist for the problem. Take for example this:

var input = "1.234.567.890,123456";
var input2 = Regex.Replace(input, @"[^\d,]+", "");

var split = input2.Split(',');
var totalLength = split[0].Length + split[1].Length;

Nothing fancy. But it works, unlike the other solutions provided until now.

But what about different culture settings? Different cultures use different thousand separators. That's where something like Double.TryParse can come in:

var input = "1.234.567.890,123456";

var style = NumberStyles.Number;
var culture = CultureInfo.CreateSpecificCulture("nl-NL");

double result;
if (double.TryParse(input, style, culture, out result))
{
    Console.WriteLine("It worked!");
}
else
{
    Console.WriteLine("Not valid");
}

The above works because the nl-NL culture uses the format. Set it to en-US and it will fail.

Neither really use a Regex to get the job done, but they can still produce the desired result.

Upvotes: 4

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626932

I think you need

^(?:\d{1,3}(?:\.\d{3}){0,4}|\d{1,15})(?:,\d{1,6})?$

See the regex demo

The integer part only allows 1 to 15 digits (or 5 groups of 3-digit chunks separated with . digit grouping symbol), and optionally followed with a comma and 1 to 6 decimal digits.

  • ^ - start of string
  • (?:\d{1,3}(?:\.\d{3}){0,4}|\d{1,15}) - 2 alternatives:
    • \d{1,3}(?:\.\d{3}){0,4} - 1 to 3 digits, followed with 0 to 4 sequences of a dot (\.) and 3 digits (\d{3})
    • | - or
    • \d{1,15} - 1 to 15 digits
  • (?:,\d{1,6})? - optional sequence (1 or 0 occurrences) of a comma followed with 1 to 6 digits
  • $ - end of string

Upvotes: 4

Huso
Huso

Reputation: 1486

Try this: ^[\d\.\,]{1,15}([\.\,]\d{0,6})?$

Upvotes: 1

Related Questions