aurelius
aurelius

Reputation: 4076

How to limit total number of digits in a decimal number

I have this regex which validates if a string is a decimal number. Also this checks if it has at most 9 decimals after ".".

^[-]?[0-9]+([\.][0-9]{0,9})?$

I need to add another check, which limits the total number of digits.

Mention: I need the total number of digits to be less then 38, including the decimal after the point, thus I cannot add the range just to decimals before the point.

valid ex:

      -12345678901234567890123456789.123456789

      123456789012345678901234567890.1

      -1.123456789

Upvotes: 0

Views: 168

Answers (2)

Pranav C Balan
Pranav C Balan

Reputation: 115222

You can use regex with positive look ahead assertion /^-?(?=[.\d]{0,39}$)\d{0,38}(\.\d{1,9})?$/

$('input').on('input', function() {
  $(this).css('color', /^-?(?=[.\d]{0,39}$)\d{0,38}(\.\d{1,9})?$/.test(this.value) ? 'green' : 'red');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input>

Regex explanation

Regular expression visualization

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626845

Use a negative lookahead:

^(?=(?:\D*\d){n}\D*$)[-]?[0-9]+(?:\.[0-9]{0,9})?$
 ^^^^^^^^^^^^^^^^^^^^

Where n is the limit argument for the amount of digits in the input string.

Example:

^(?=(?:\D*\d){7}\D*$)-?[0-9]+(?:\.[0-9]{0,9})?$

will match 1234.567, but will not match 1234.56 and 1234.5678.

See the regex demo

Now,

I need the total number of digits to be less then 38

Just use a negative lookahead:

^(?!(?:\D*\d){38})-?[0-9]+(?:\.[0-9]{0,9})?$
 ^^^^^^^^^^^^^^^^^

This (?!(?:\D*\d){38}) lookahead will fail the match if there are 38 (not obligatorily consecutive due to \D*) digits in the string.

Pattern explanation:

  • ^ - start of string
  • (?!(?:\D*\d){38}) - the negative lookahead that will try to match 0+ non-digits (\D*) followed with a digit exactly 38 times and if it matches that text, no match will be returned
  • -? - an optional (1 or 0) hyphen (no need to place it into a character class as it is not a special regex metacharacter here)
  • [0-9]+ - 1+ digits (use \d instead to make it shorter)
  • (?:\.[0-9]{0,9})? - an optional (1 or 0 occurrences) sequence of:
    • \. - a literal dot
    • [0-9]{0,9} - 0 to 9 digits (again, \d{0,9} is shorter)
  • $ - end of string

And if you need to only check the integer part to have less than 38 digits, use

^(?!(?:[^\d.]*\d){38})[-]?[0-9]+(?:\.[0-9]{0,9})?$

See this regex demo

Upvotes: 3

Related Questions