7

Could anybody provide a regular expression for a number that has to be between 1 and 17 in length, and could optionally contain a mantissa of up to 4 places? The length of 17 includes both the characteristic and the mantissa.

Edit:

The length of 17 excludes the decimal point.

Valid examples:

12345678901234567 
1234567890123.4567 
123456789012345.67
12.34

Invalid:

12345678901234.5678 (Length of numerals = 18)

Thanks.

3
  • 2
    Can you provide some examples. Does the 17 length also include the decimal point ? Commented Mar 3, 2010 at 6:12
  • Excluding the decimal point. Valid examples: 12345678901234567 1234567890123.4567 123456789012345.67 Invalid: 12345678901234.5678 (Length of numerals = 18) Commented Mar 3, 2010 at 6:17
  • 1
    @PR: It is better to update your question with this type of information :) Commented Mar 3, 2010 at 7:18

6 Answers 6

5
^\d{17}$|^\d{13}(?=.{5}$)\d*\.\d*\d$

Regex explained:

^\d{17}$    //A string of 17 digits 
|           //or
^\d{13}     //13 digits followed by
(?=.{5}$)   //5 characters, of which 
\d*\.\d*    //one is a decimal point and others are digits
\d$         //and the last one is a digit
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Amarghosh, this did the trick. Although, I had to tweak it a bit as 12.34 was failing. Here's what I did: ^\d{1,17}$|^\d{1,13}(?=.{1,5}$)\d*\.\d*\d$ Thanks.
@PR The original question was for "a number that has to be 17 in length" - I posted this before you edited it to make "between 1 to 17"
yes, my mistake. I should've been clearer with my question. Thanks. :)
4

OK, this is the best I could do:

/^\d{1,17}$|(?=^.{1,18}$)^\d+\.\d{1,4}$/

Basically, match 1-17 digits, or strings of length 1-18 which consist of two sets of digits separated by a period. The right set can only contain between 1-4 digits.

4 Comments

it matches 1234567890.1234567, you need to add a $ at the end of the 1 to 4 digits.
It doesn't match that string. Care to double check?
perl -e 'print "matched\n" if "1234567890.1234567" =~ /(^\d{17}$)|((?=^.{18}$)(\d+\.\d{1,4}))/'
Ah, gotcha. I'm using Java. You're right. Try the new version.
2

Don't do this completely in regex. The problem becomes nearly trivial in most programming languages, and that way will be easier for you to write, verify, test, and maintain. You can still use regex for part of the solution, of course, but you don't have to. Pseudocode:

m = re.match(r"(?P<before>[0-9]+)(?P<after>\.[0-9]{1,4})?$", input_string)
if not m:
  return "no match"
before, after = m.group("before", "after")
after = after[1:] if after else ""  # remove period or set to empty string
if len(before) + len(after) > 17:
  return "incorrect length"
return "valid"

Comments

1

It's not particularly pretty, but with so few possibilities (0,1,2,3,4 length mantissa) I would probably just list them all:

\d{17}|\d{16}\.\d{1}|\d{15}\.\d{2}|\d{14}\.\d{3}|\d{13}\.\d{4}

3 Comments

No, doesn't work. I tried modifying it too like this: \d{1,17}|\d{1,16}\.\d{0,1}|\d{1,15}\.\d{0,2}|\d{1,14}\.\d{0,3}|\d{1,13}\.\d{0,4}
Which language are you using for this, or what is the regex going into? That one worked for me, but it's going to depend on the interpreter.
I'm using the ASP.NET RegexValidator control.
0

in your favourite language, you can do a couple of logical checks, eg Python

num="1234567890133.3456"
if "." in num and len(num)==17 :
     n=num.split(".")
     if len(n[1])>4:
         print "cannot have more than 4 decimal places"
     elif len(n)==2 and n[0].isdigit() and n[1].isdigit():
         print "yes, decimal"
elif len(num)==17 and num.isdigit():
     print "%s is number with no decimal and is exactly 17 digits." % num
else:
     print "%s not ok, check length is 17" % num

Comments

-1

I have created this regex from above great solutions. may it help any one. Please let me know if you find any bug in it.
String decimalRegex =""+ "^(?!0[\d,])\+?" + // ^ Start of Number
"(\d{0,"+size+"}|" + // Numeric value without group symbol | (OR)
"(\d{0,"+rem(size,groupSize)+"},)?"+
"(\d{0,"+groupSize+"},) {0,"+div(size,groupSize)+"}\d{"+groupSize+"})" + // Numeric value with group symbol
"((([a-zA-Z]{0,2}|\"|\')\s?\+?)|\.)"+
"(\d{0,"+scale+"})?" + // Decimal value without group symbol
"(\s?([a-zA-Z]{0,2}|\"|\'))$"; // Ends with

private int rem(int size,int groupSize ){
    int rem = (size - groupSize)%groupSize;
    return rem;
}

private int div(int size,int groupSize ){
    int div = (size - groupSize)/groupSize;
    return div;
}

1 Comment

This does not answer the question at all

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.