views:

141

answers:

8

Hi,

I need to validate the below range via regex in javascript.

-20.00 to +20.00 with an increment of 0.5.

The user should be able to enter the 1.50 as well instead of +01.50.

I tried to do a lot of research in google, though regex is not easy. If I understand it correctly, then I will need to split up the regex into smaller groups. From a programmers view, I would think, that I need to validate each "char" that was keyed into the input field. If I understand how grouping works in regex then I guess I could do the regex myself. So please help me to understand regex with the above problem, don't just throw the regex in :)

Thanks,

A: 

May be the simpler way to check that you have 2 valid numbers float numbers (regex is good but also parseFloat could be used) and at last step check programmaticly that these numbers are in the range [-20.0 - 20.0]

Dewfy
A: 

The regex you want is:

/[-+]?([01]?[0-9](\.[05]0?)?|(20(\.00?)?)/

This breaks down into:

[-+]?  : an optional - or +
( 
 [01]?  : an optional 0 or
 [0-9]  : number 0-9
 (...)? : Optional
  \.    : .
  [05]  : 0 or 5
  0?    : Optional 0

  |      : OR

  20     : numbers 20
  (...)? : Optional
   \.    : .
   00?   : O or OO
)

Note this would allow the odd corner case of "-00.00"

Callum
Lieven
Updated based on comment
Callum
A: 

The parts of regex which you want to take advantage of are:

? - optional operator. e.g. at the beginning you would want something like [-+]? which means the user can optionally have a + or a - sign.

[] - Character classes as above, [-+] means either the character - or + (the \ is because - has special meaning inside a character class)

\d - means numberical digit

{} - Repitition, \d{1,2} matches between 1 and 2 \d's

So your regex would look something like this: [-+]?\d{1,2}.[05]0

Salgar
+4  A: 

It doesn't really make sense to use a regular expression to validate a numeric value.

Try:

function checkRange(input) {
    var value = parseFloat(input);
    return (!isNaN(value) && (value >= -20) && (value <= 20) && (value % 0.5 == 0));
}
NickFitz
I guess I need to make sure that the user enters the value in the correct format.
vikasde
A: 

This should be done in two steps. First step is to use a regular expression to make sure that the entered value is textually valid (i.e., it has x number of decimal numbers, it has a sign, etc.) Then convert it to a value to make sure that it is logically valid.

So first of all, you might want a regular expression like this:

/^[+-]?\d{1,2}\.(00|50)$/

It will:

  • Ensure that string optionally begins with + or -.
  • Followed by one or two numbers.
  • Followed by a dot.
  • Followed by 00 or 50

After that, you can ensure that it is in the range of -20 to 20:

var floatValue = Number(value);
if (floatValue < -20 || floatValue > 20) {
    // Invalid!
}
Blixt
A: 

As mentioned, ranges are better matched using numbers, but use regexes to make sure the format after the decimal is correct.

var value = ... // eg. "-20.05"
var number = parseFloat(value);
if (number >= -20 && number <= 20 && /[+-]?\d+\.[05]0/.test(value)) {
   alert("in range")
} else {
   alert("out of range")
}
Ben Lings
+1  A: 

Following should do it

var myregexp = /^[+-]?(20\.00|[01?][0-9]\.[05]0)$/m;
if (subject.match(myregexp)) {
    // Successful match
} else {
    // Match attempt failed
}

// ^[+-]?(20\.00|[01?][0-9]\.[05]0)$
// 
// Options: ^ and $ match at line breaks
// 
// Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
// Match a single character present in the list below «[+-]?»
//    Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    The character “+” «+»
//    The character “-” «-»
// Match the regular expression below and capture its match into backreference number 1 «(20\.00|[01?][0-9]\.[05]0)»
//    Match either the regular expression below (attempting the next alternative only if this one fails) «20\.00»
//       Match the characters “20” literally «20»
//       Match the character “.” literally «\.»
//       Match the characters “00” literally «00»
//    Or match regular expression number 2 below (the entire group fails if this one fails to match) «[01?][0-9]\.[05]0»
//       Match a single character present in the list “01?” «[01?]»
//       Match a single character in the range between “0” and “9” «[0-9]»
//       Match the character “.” literally «\.»
//       Match a single character present in the list “05” «[05]»
//       Match the character “0” literally «0»
// Assert position at the end of a line (at the end of the string or before a line break character) «$»
Lieven
You could pull the 0? forward to the one, forming [01]?
Don Johe
@Don Johe: you are right. Updated the answer to reflect the shorter version of the regex.
Lieven
Thanks. Very well explained. That will do the trick for me and make sure that I can use regex from now on :)
vikasde
A: 

The following regex should work:

^[+-]?(?:20\.?0{0,2}?|[01]?[0-9]\.?[05]?0?)$

Explanation:

^                             # anchor the match at the start of the string
   [+-]?                      # optional sign
   (?:                        # non-capturing group for alternation:
      20\.?0{0,2}?            # match either 20 (optionally followed by . or .0 or .00)
   |                          # or
      [01]?[0-9]\.?[05]?0?    # match 00-19 (optionally followed by . or .0 or .5 or .50 or .00)
   )                          # end of alternation
$                             # anchor the match at the end of the string
Tim Pietzcker