tags:

views:

183

answers:

5

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  A: 

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.

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

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"
Roger Pate
A: 

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
ghostdog74
+1  A: 

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}
Chad Birch
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}
Prakash
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.
Chad Birch
I'm using the ASP.NET RegexValidator control.
Prakash
+4  A: 
^\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
Amarghosh
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.
Prakash
@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"`
Amarghosh
@Amarghosh, yes, my mistake. I should've been clearer with my question. Thanks. :)
Prakash