102

How can I check if a given number is within a range of numbers?

kenorb
  • 155,785
  • 88
  • 678
  • 743
Richard Peers
  • 1,131
  • 3
  • 9
  • 7
  • 1
    Related: [How to check if integer is between a range?](http://stackoverflow.com/q/5029409/55075) – kenorb Mar 12 '15 at 18:41

16 Answers16

175

The expression:

($min <= $value) && ($value <= $max)

will be true if $value is between $min and $max, inclusively

See the PHP docs for more on comparison operators

Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Dancrumb
  • 26,597
  • 10
  • 74
  • 130
  • 1
    No it won't. Both comparison operators should be <=, or the operands of the second part of the expression should be swapped. ($value should not be greater than $max). – GolezTrol Jan 13 '11 at 19:00
  • 1
    You must have added that comment while I was correcting my error... this expression is now correct – Dancrumb Jan 13 '11 at 19:02
  • 3
    Depending on whether the OP really means "integer" when asking for "integer" this will produce false results when `$value` is a float. Also, since the comparison is loose, passing a string might produce false result, e.g. `(0 <= 'string') && ('string' <= 10) );` is `true` due to type juggling. – Gordon Jan 13 '11 at 19:14
  • @Gordon, only if you wish the boundary values to be treated inclusively... but a valid point, nonetheless – Dancrumb Jan 14 '11 at 16:37
  • While it's true that the PHP interpreter does not require the parentheses, it's a matter of style as to whether it is helpful to engineers. Personally, I like the explicit nature of the parentheses in this expression and I don't think they add clutter. However, I think that they would start to feel noisy if you include the `(int)` casts. In that instance, I would probably elect to leave them out. – Dancrumb Oct 11 '16 at 14:40
  • there is no provided helper function in PHP to check if a number between 2 numbers? – Ebrahim Bashirpour Feb 14 '21 at 09:04
  • I'd recommend dropping the parenthesis but using `and` instead of `&&` because `and` has much lower precendence (in case the code is later changed a lot). – Mikko Rantalainen Jan 19 '23 at 09:28
  • Certainly approach, but personally, I think knowledge of order of precedence should not be relied upon to make an expression understandable on first reading. It's necessary for definitively resolving an expression, but for human readers, I think that's too high and cognitive demand – Dancrumb Jan 19 '23 at 13:45
  • It's really missing a Python-like syntax: `$min <= $value <= $max` – Epoc Jun 29 '23 at 14:16
134

You can use filter_var

filter_var(
    $yourInteger, 
    FILTER_VALIDATE_INT, 
    array(
        'options' => array(
            'min_range' => $min, 
            'max_range' => $max
        )
    )
);

This will also allow you to specify whether you want to allow octal and hex notation of integers. Note that the function is type-safe. 5.5 is not an integer but a float and will not validate.

Detailed tutorial about filtering data with PHP:

jagb
  • 912
  • 11
  • 26
Gordon
  • 312,688
  • 75
  • 539
  • 559
53

Might help:

if ( in_array(2, range(1,7)) ) {
    echo 'Number 2 is in range 1-7';
}

http://php.net/manual/en/function.range.php

Bobz
  • 2,345
  • 2
  • 18
  • 22
  • 25
    Worth noting that has a memory cost due to the generation of the range. – Dancrumb Dec 01 '17 at 16:24
  • 6
    @pr1nc3 but this solution is very slow and very memory hungry when it's a large range. – hanshenrik Jan 02 '19 at 18:06
  • Agreed, this is way less elegant than the accepted solution and it will take much longer to execute on larger arrays because you have to perform a search on the array to find the value. It's faster, less memory hungry, and just as few lines to use the accepted solution. – dmcoding Aug 17 '21 at 18:02
  • Does not handle float values – Richard Muvirimi Feb 21 '22 at 12:39
23

You could whip up a little helper function to do this:

/**
 * Determines if $number is between $min and $max
 *
 * @param  integer  $number     The number to test
 * @param  integer  $min        The minimum value in the range
 * @param  integer  $max        The maximum value in the range
 * @param  boolean  $inclusive  Whether the range should be inclusive or not
 * @return boolean              Whether the number was in the range
 */
function in_range($number, $min, $max, $inclusive = FALSE)
{
    if (is_int($number) && is_int($min) && is_int($max))
    {
        return $inclusive
            ? ($number >= $min && $number <= $max)
            : ($number > $min && $number < $max) ;
    }

    return FALSE;
}

And you would use it like so:

var_dump(in_range(5, 0, 10));        // TRUE
var_dump(in_range(1, 0, 1));         // FALSE
var_dump(in_range(1, 0, 1, TRUE));   // TRUE
var_dump(in_range(11, 0, 10, TRUE)); // FALSE

// etc...
Vincent Savard
  • 34,979
  • 10
  • 68
  • 73
Luke
  • 3,985
  • 1
  • 20
  • 35
11
if (($num >= $lower_boundary) && ($num <= $upper_boundary)) {

You may want to adjust the comparison operators if you want the boundary values not to be valid.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
7

You can try the following one-statement:

if (($x-$min)*($x-$max) < 0)

or:

if (max(min($x, $max), $min) == $x)
kenorb
  • 155,785
  • 88
  • 678
  • 743
  • 1
    `min()` and `max()` will use comparision in the actual hardware implementation so doing both `min` and `max` and single comparision will result in always doing three in total. Instead, simply writing `if ($min < $x and $x < $max)` which will do two comparisions *in worst* case and only one if the value `$x` is smaller than `$min` limit. The variant with multiplication might be faster with assembler because it can use CPU pipelining very effectively but in case of PHP, I'd recommend testing that instead of assuming it's better than two compariosions with shortcut `and` in between. – Mikko Rantalainen Jan 19 '23 at 09:32
7

Some other possibilities:

if (in_array($value, range($min, $max), true)) {
    echo "You can be sure that $min <= $value <= $max";
}

Or:

if ($value === min(max($value, $min), $max)) {
    echo "You can be sure that $min <= $value <= $max";
}

Actually this is what is use to cast a value which is out of the range to the closest end of it.

$value = min(max($value, $min), $max);

Example

/**
 * This is un-sanitized user input.
 */
$posts_per_page = 999;

/**
 * Sanitize $posts_per_page.
 */
$posts_per_page = min(max($posts_per_page, 5), 30);

/**
 * Use.
 */
var_dump($posts_per_page); // Output: int(30)
Nabil Kadimi
  • 10,078
  • 2
  • 51
  • 58
1

using a switch case

    switch ($num){

        case ($num>= $value1 && $num<= $value2): 
            echo "within range 1";
        break;
        case ($num>= $value3 && $num<= $value4): 
            echo "within range 2";
        break;
        .
        .
        .
        .
        .

        default: //default
            echo "within no range";
        break;
     }
Jefkine Kafunah
  • 126
  • 1
  • 5
  • 4
    Should be `switch(true)`, otherwise if `$num == 0`, the case logic fails because PHP tries to match `0 == ($num>= $value1 && $num<= $value2)`, etc. I've suggested this as an edit. – Zane Nov 30 '15 at 05:28
1

I've created a simple helper function.

if ( !function_exists('number_between') )
{
    /**
     * number_between
     * 
     * @param {integer} $number
     * @param {array} $range [min, max]
     * @return {boolean}
     */
    function number_between(
            int $number, 
            array $range
    ){
        
        if(
                count($range) !== 2 || 
                is_numeric($range[0]) === FALSE || 
                is_numeric($range[1]) === FALSE
        ){
            throw new \Exception("number_between second parameter must contain two numbers.", E_WARNING);
        }
        
        if( 
                in_array($number, range($range[0], $range[1]))
        ){
            return TRUE;
        }else{
            return FALSE;
        }
    }
    
}
David Clews
  • 795
  • 6
  • 14
0

Another way to do this with simple if/else range. For ex:

$watermarkSize = 0;

if (($originalImageWidth >= 0) && ($originalImageWidth <= 640)) {
    $watermarkSize = 10;
} else if (($originalImageWidth >= 641) && ($originalImageWidth <= 1024)) {
    $watermarkSize = 25;
} else if (($originalImageWidth >= 1025) && ($originalImageWidth <= 2048)) {
    $watermarkSize = 50;
} else if (($originalImageWidth >= 2049) && ($originalImageWidth <= 4096)) {
    $watermarkSize = 100;
} else {
    $watermarkSize = 200;
}
Gajen Sunthara
  • 4,470
  • 37
  • 23
0

I created a function to check if times in an array overlap somehow:

    /**
     * Function to check if there are overlapping times in an array of \DateTime objects.
     *
     * @param $ranges
     *
     * @return \DateTime[]|bool
     */
    public function timesOverlap($ranges) {
        foreach ($ranges as $k1 => $t1) {
            foreach ($ranges as $k2 => $t2) {
                if ($k1 != $k2) {
                    /* @var \DateTime[] $t1 */
                    /* @var \DateTime[] $t2 */
                    $a = $t1[0]->getTimestamp();
                    $b = $t1[1]->getTimestamp();
                    $c = $t2[0]->getTimestamp();
                    $d = $t2[1]->getTimestamp();

                    if (($c >= $a && $c <= $b) || $d >= $a && $d <= $b) {
                        return true;
                    }
                }
            }
        }

        return false;
    }
Link
  • 29
  • 5
0

Here is my little contribution:

function inRange($number) {
  $ranges = [0, 13, 17, 24, 34, 44, 54, 65, 200];
  $n = count($ranges);

  while($n--){
    if( $number > $ranges[$n] )
      return $ranges[$n]+1 .'-'. $ranges[$n + 1];
  }
Miquel
  • 59
  • 1
  • 2
0
$ranges = [
    1 => [
        'min_range' => 0.01,
        'max_range' => 199.99
    ],
    2 => [
        'min_range' => 200.00,
    ],
];

foreach($ranges as $value => $range){
    if(filter_var($cartTotal, FILTER_VALIDATE_FLOAT, ['options' => $range])){
        return $value;
    }
}
0

I have function for my case

Use:

echo checkRangeNumber(0);
echo checkRangeNumber(1);
echo checkRangeNumber(499);
echo checkRangeNumber(500);
echo checkRangeNumber(501);
echo checkRangeNumber(3001);
echo checkRangeNumber(999);

//return

0
1-500
1-500
1-500
501-1000
3000-3500
501-1000

function checkRangeNumber($number, $per_page = 500)
{
    //$per_page = 500; // it's fixed number, but... 

    if ($number == 0) {
        return "0";
    }

    $num_page = ceil($number / $per_page); // returns 65
    $low_limit = ($num_page - 1) * $per_page + 1; // returns 32000
    $up_limit = $num_page * $per_page; // returns 40
    return  "$low_limit-$up_limit";
}
Hoàng Vũ Tgtt
  • 1,863
  • 24
  • 8
-1
function limit_range($num, $min, $max)
{
  // Now limit it
  return $num>$max?$max:$num<$min?$min:$num;
}

$min = 0;  // Minimum number can be
$max = 4;  // Maximum number can be
$num = 10;  // Your number
// Number returned is limited to be minimum 0 and maximum 4
echo limit_range($num, $min, $max); // return 4
$num = 2;
echo limit_range($num, $min, $max); // return 2
$num = -1;
echo limit_range($num, $min, $max); // return 0
Justin Levene
  • 1,630
  • 19
  • 17
-2

Thank you so much and I got my answer by adding a break in the foreach loop and now it is working fine.

Here are the updated answer:

foreach ($this->crud->getDataAll('shipping_charges') as $ship) {
  if ($weight >= $ship->low && $weight <= $ship->high) {
      $val = $ship->amount;
      break;
      }
      else
      {
        $val = 900;
      }
     }
     echo $val ;
Code GuruDev
  • 348
  • 3
  • 11