198

I want to check if a value is in an accepted range. If yes, to do something; otherwise, something else.

The range is 0.001-0.009. I know how to use multiple if to check this, but I want to know if there is any way to check it in a single if statement.

0

10 Answers 10

354

You're asking a question about numeric comparisons, so regular expressions really have nothing to do with the issue. You don't need "multiple if" statements to do it, either:

if (x >= 0.001 && x <= 0.009) {
  // something
}

You could write yourself a "between()" function:

function between(x, min, max) {
  return x >= min && x <= max;
}
// ...
if (between(x, 0.001, 0.009)) {
  // something
}
Sign up to request clarification or add additional context in comments.

Comments

83

Here is an option with only a single comparison.

// return true if in range, otherwise false
function inRange(x, min, max) {
    return ((x-min)*(x-max) <= 0);
}

console.log(inRange(5, 1, 10));     // true
console.log(inRange(-5, 1, 10));    // false
console.log(inRange(20, 1, 10));    // false

7 Comments

This is sweet it doesn't matter if min is lower or max is lower it will still work. In fact it might be better to call min, max something like start, end. great algo either way thanks!
Won't somebody PLEASE think of the time complexity!? I'd go with the accepted solution because two comparisons at Θ(2) is better than one comparison and three arithmetic operations at O(4).
I never claimed it to be whatever you imagined yourself it is. It is a viable option, nevertheless.
This is a little silly, it's not only probably slower but also much less obvious as to what the code does
@MattMcCarthy : if you're counting the the math one as O(4) then you need to also count O(3) for the 2 comparison one, since && isn't a free lunch. I submitted a totally different O(3) solution below with 3 comparisons in a continuous chain, sans the &&, after inverting one of the boolean questions being asked.
|
24

If you must use a regexp (and really, you shouldn't!) this will work:

/^0\.00([1-8]\d*|90*)$/

should work, i.e.

  • ^ nothing before,
  • followed by 0.00 (nb: backslash escape for the . character)
  • followed by 1 through 8, and any number of additional digits
  • or 9, followed by any number of zeroes
  • $: followed by nothing else

1 Comment

LOL LOL LOL LOL
21

If you're already using lodash, you could use the inRange() function: https://lodash.com/docs/4.17.15#inRange

_.inRange(3, 2, 4);
// => true

_.inRange(4, 8);
// => true

_.inRange(4, 2);
// => false

_.inRange(2, 2);
// => false

_.inRange(1.2, 2);
// => true

_.inRange(5.2, 4);
// => false

_.inRange(-3, -2, -6);
// => true

Comments

5

You must want to determine the lower and upper bound before writing the condition

function between(value,first,last) {

 let lower = Math.min(first,last) , upper = Math.max(first,last);
 return value >= lower &&  value <= upper ;

}

Comments

5

Here's a short ES6 function:

const inRange = (num, min, max) => num >= min && num <= max

Comments

4

I like Pointy's between function so I wrote a similar one that worked well for my scenario.

/**
 * Checks if an integer is within ±x another integer.
 * @param {int} op - The integer in question
 * @param {int} target - The integer to compare to
 * @param {int} range - the range ±
 */
function nearInt(op, target, range) {
    return op < target + range && op > target - range;
}

so if you wanted to see if x was within ±10 of y:

var x = 100;
var y = 115;
nearInt(x,y,10) = false

I'm using it for detecting a long-press on mobile:

//make sure they haven't moved too much during long press.
if (!nearInt(Last.x,Start.x,5) || !nearInt(Last.y, Start.y,5)) clearTimeout(t);

Comments

4

If you want your code to pick a specific range of digits, be sure to use the && operator instead of the ||.

if (x >= 4 && x <= 9) {
  // do something
} else {
  // do something else
}

// be sure not to do this

if (x >= 4 || x <= 9) {
  // do something
} else {
  // do something else
}

Comments

2

const inRange = (num, num1, num2) => Math.min(num1, num2) <= num && Math.max(num1, num2) >= num;

Could be like this if you want to make inRange inclusive and not depend on order of range numbers (num1, num2).

Comments

1

Skip all the multiplications, max()/min() function calls, or logical AND (&&), and just do

function in_range(_, __, ___) {

    return ((_ = +_) < +__) < (_ <= +___)
}

in_range(n, 0.001, 0.009)

It works because the boolean outcome described by this triple compare chain is inquiring whether

 n <= max is TRUE but also
 n <  min is FALSE

Which is same as inquiring about being within the [min, max] range. The logical equivalent is not(not A) and B, which is just another way of saying A and B. The comparison operators are so low-cost whether a short-circuiting && saves time is questionable.

0.0010
0.0011
0.0012
0.0013
0.0014
0.0015
.
.
.

0.0087
0.0088
0.0089
0.0090

A similar function can also be created for string comparisons in the same manner by removing the forced numeric coercions :

function in_range_str(_, __, ___) {

    return (_ < __) < (_ <= ___)
}

So instead of having to invoke regex or check its byte ordinal value, one can test whether a byte is a uppercase letter in ASCII by doing

in_range_str(chr1, "A", "Z")

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.