简体   繁体   中英

How to check if an integer is within a range?

Is there a way to test a range without doing this redundant code:

if ($int>$min && $int<$max)

?

Like a function:

function testRange($int,$min,$max){
    return ($min<$int && $int<$max);
}

usage:

if (testRange($int,$min,$max)) 

?

Does PHP have such built-in function? Or any other way to do it?

Tested your 3 ways with a 1000000-times-loop.

t1_test1: ($val >= $min && $val <= $max) : 0.3823 ms

t2_test2: (in_array($val, range($min, $max)) : 9.3301 ms

t3_test3: (max(min($var, $max), $min) == $val) : 0.7272 ms

T1 was fastest, it was basicly this:

function t1($val, $min, $max) {
  return ($val >= $min && $val <= $max);
}

I don't think you'll get a better way than your function.

It is clean, easy to follow and understand, and returns the result of the condition (no return (...) ? true : false mess).

There is no builtin function, but you can easily achieve it by calling the functions min() and max() appropriately.

// Limit integer between 1 and 100000
$var = max(min($var, 100000), 1);

Most of the given examples assume that for the test range [$a..$b], $a <= $b, ie the range extremes are in lower - higher order and most assume that all are integer numbers.
But I needed a function to test if $n was between $a and $b, as described here:

Check if $n is between $a and $b even if:
    $a < $b  
    $a > $b
    $a = $b

All numbers can be real, not only integer.

There is an easy way to test.
I base the test it in the fact that ($n-$a) and ($n-$b) have different signs when $n is between $a and $b, and the same sign when $n is outside the $a..$b range.
This function is valid for testing increasing, decreasing, positive and negative numbers, not limited to test only integer numbers.

function between($n, $a, $b)
{
    return (($a==$n)&&($b==$n))? true : ($n-$a)*($n-$b)<0;
}

I'm not able to comment (not enough reputation) so I'll amend Luis Rosety's answer here:

function between($n, $a, $b) {
    return ($n-$a)*($n-$b) <= 0;
}

This function works also in cases where n == a or n == b.

Proof: Let n belong to range [a,b], where [a,b] is a subset of real numbers.

Now a <= n <= b. Then na >= 0 and nb <= 0. That means that (na)*(nb) <= 0.

Case b <= n <= a works similarly.

There's filter_var() as well and it's the native function which checks range . It doesn't give exactly what you want (never returns true), but with "cheat" we can change it.

I don't think it's a good code as for readability, but I show it's as a possibility:

return (filter_var($someNumber, FILTER_VALIDATE_INT, ['options' => ['min_range' => $min, 'max_range' => $max]]) !== false)

Just fill $someNumber , $min and $max . filter_var with that filter returns either boolean false when number is outside range or the number itself when it's within range. The expression ( !== false ) makes function return true, when number is within range.

If you want to shorten it somehow, remember about type casting. If you would use != it would be false for number 0 within range -5; +5 (while it should be true). The same would happen if you would use type casting ( (bool) ).

// EXAMPLE OF WRONG USE, GIVES WRONG RESULTS WITH "0"
(bool)filter_var($someNumber, FILTER_VALIDATE_INT, ['options' => ['min_range' => $min, 'max_range' => $max]])
if (filter_var($someNumber, FILTER_VALIDATE_INT, ['options' => ['min_range' => $min, 'max_range' => $max]])) ...

Imagine that (from other answer):

if(in_array($userScore, range(-5, 5))) echo 'your score is correct'; else echo 'incorrect, enter again';

If user would write empty value ( $userScore = '' ) it would be correct, as in_array is set here for default, non-strict more and that means that range creates 0 as well, and '' == 0 (non-strict), but '' !== 0 (if you would use strict mode). It's easy to miss such things and that's why I wrote a bit about that. I was learned that strict operators are default, and programmer could use non-strict only in special cases . I think it's a good lesson. Most examples here would fail in some cases because non-strict checking.

Still I like filter_var and you can use above (or below if I'd got so "upped" ;)) functions and make your own callback which you would use as FILTER_CALLBACK filter. You could return bool or even add openRange parameter. And other good point: you can use other functions , eg checking range of every number of array or POST/GET values. That's really powerful tool.

Using comparison operators is way, way faster than calling any function. I'm not 100% sure if this exists, but I think it doesn't.

You could do it using in_array() combined with range()

if (in_array($value, range($min, $max))) {
    // Value is in range
}

Note As has been pointed out in the comments however, this is not exactly a great solution if you are focussed on performance. Generating an array (escpecially with larger ranges) will slow down the execution.

One possibility (not a solution):

$mysqli->query("SELECT $value BETWEEN $min and $max as test")->fetch_object()->test;

This is an expansion on the answer provided by @Mark Paspirgilis, allows for selectable inclusion and returns a Boolean response.

public function between($p_value, $p_min, $p_max, $p_inclusive=0) {
  ## 0 = all inclusive; -1 = left inclusive; 1 = right inclusive
  if ($p_inclusive == -1) {
    return (bool)($p_value >= $p_min && $p_value < $p_max);
  }
  else if ($p_inclusive == 1) {
    return (bool)($p_value > $p_min && $p_value <= $p_max);
  }
  else {
    return (bool)($p_value >= $p_min && $p_value <= $p_max);
  }
} # END FUNCTION between

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM