如何检查整数是否在范围内?


71

有没有一种方法可以在不执行此冗余代码的情况下测试范围:

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

就像一个函数:

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

用法:

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

PHP是否具有这样的内置功能?还是其他方式可以做到?


9
有一种使用in_array()和的可怕方法range()。除此之外,我不认为有一个
Pekka

8
您为什么将其称为“冗余代码”?这是必须评估的,不是吗?
Nanne 2011年

3
确实。那个原始的快速,易读代码的哪一部分是多余的?谁会知道只要阅读对您的testRange()的调用,testRange(1、1、2)是对还是错?
马特·吉布森

4
我认为他指的是必须在条件中两次指定相同的变量。尽管我同意一种可以让您说的语言构造if($int between $min and $max)很好,但是我恐怕只看到一种语言是SQL。
Wes P

2
@是,就我个人而言,我认为使用函数会引入更多出错的可能性-例如,可能会以错误的顺序获取参数。另外,您是否想添加另一个函数进行比较($ int> = $ min && $ int <= $ max),这是另一个非常常见的比较?我想如果您要一遍又一遍地编写此特定代码,那么如果您不介意开销的话,可以使用一个函数,但是是的,您必须自己动手,因为其中没有内置的函数在PHP中。(不过,我并不是匿名的匿名投票者,只是对谈论事情感兴趣;))
Matt Gibson

Answers:


47

我认为您不会获得比您的功能更好的方法。

它是干净的,易于遵循和理解的,并返回条件的结果(无return (...) ? true : false混乱)。


92

使用1000000次循环测试了您的3种方式。

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

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

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

T1最快,基本上是这样的:

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

这就是我所期望的:)
Alex

1
真好!因为我需要它告诉我是对还是错,所以我添加了以下内容:function t1($val, $min, $max) { if ($val >= $min && $val <= $max) {return true;} else {return false;} }
Pathros

12
@pathros上面的函数已经返回truefalse,无需编写其他代码
SBH

也不需要使用括号。“返回$ val> = $ min && $ val <= $ max;” 足够的。
ElChupacabra '16

2
我认为问题不在于性能。其他语言为此提供了本机运算符,我认为这就是OP所追求的。
乔什·约翰逊

16

没有内置函数,但是你可以很容易地通过调用函数实现它min()max()适当的。

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

6
这很有趣。但是,我不会纯粹出于可读性的目的使用它。
aalaap

如上所述,这个想法确实很有趣,但是很难阅读,它调用了两个可以避免的函数。
AnthonyB

10

给出的大多数示例都假设对于测试范围[$ a .. $ b],$ a <= $ b,即范围的极端值较低-较高阶,并且大多数都假设它们都是整数。
但是我需要一个函数来测试$ n是否在$ a和$ b之间,如下所述:

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

All numbers can be real, not only integer.

有一种简单的测试方法。
我进行测试的依据是,当$ n在$ a和$ b之间时,($n-$a)($n-$b)具有不同的符号;当$ n超出$ a .. $ b范围时,具有相同的符号。
此功能适用于测试递增,递减,正数和负数,而不仅限于测试整数。

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

2
很好 请注意,如果$ n,$ a和$ b可能有相同的数字,则此函数将返回false,而其他大多数函数将返回true。
bksunday 2015年

1
感谢@bksunday的评论。我在代码中添加了对这种情况的处理。
路易斯·罗斯蒂

我必须在@bksunday评论和答案中添加一个精度。间隔可以是打开间隔或关闭间隔。开放时间间隔不包含限制,而封闭时间间隔包含限制。因此,对于来自动态的原始问题,它是一个开放时间间隔,因此当$ a = $ b = $ n时,它应该返回false,因为它是我的原始函数,甚至更容易:开放时间间隔($ a,$ b)中$ a = $ b是一个空集。
路易斯·罗斯蒂

如果$ n = 0,并且$ a = 0和$ b = 1,则此functionjs返回FALSE。为什么?0在范围内(介于0和1之间),因此应返回TRUE
Tikky

7

我无法发表评论(信誉不足),因此我将在此处修改路易斯·罗斯蒂的回答:

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

此函数在n == a或n == b的情况下也有效。

证明:令n属于范围[a,b],其中[a,b]是实数的子集。

现在a <= n <= b。然后na> = 0且nb <=0。这意味着(na)*(nb)<= 0。

情况b <= n <= a的工作原理类似。


间隔类型(打开或关闭)很重要。开放时间间隔不包括限制,而封闭时间间隔确实包含限制。请参阅en.wikipedia.org/wiki/Interval_
数学

可以肯定的是,使用浮点数时,但是使用整数(根据问题)时,这是无关紧要的。请记住,对于所有整数a和b,(a,b)实际上是[a + 1,b-1]。
Esa Lindqvist

对我来说最好的答案
Tikky

3

也有filter_var(),它是检查range本机函数。它并不能完全提供您想要的(永远不会返回true),但是通过“作弊”我们可以更改它。

对于可读性,我认为这不是一个好的代码,但我证明它是一种可能:

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

刚填 $someNumber$min然后$maxfilter_var使用该过滤器时,如果number超出范围,则返回boolean false;如果处于范围内,则返回数字本身。!== false当数字在范围内时,表达式()使函数返回true。

如果要以某种方式缩短它,请记住有关类型转换的内容。如果您使用!=它,则数字0在-5范围内为false;否则为false。+5(这应该是正确的)。如果您使用类型转换((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]])) ...

想象一下(从其他答案中得出):

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

如果用户要写空值($userScore = ''),那将是正确的(如此in_array处默认设置),并且非严格限制更多,这意味着该范围0也会创建,并且'' == 0(非严格)但'' !== 0(如果您要使用严格模式)。很容易错过这样的事情,这就是为什么我为此写了些东西。我了解到严格的运算符是默认值,程序员仅在特殊情况下才可以使用非严格的运算符。我认为这是一个很好的教训。由于非严格检查,此处的大多数示例在某些情况下会失败。

仍然我喜欢filter_var,您可以在上面(或下面,如果我被“增加”了;)使用函数)并进行自己的回调,以用作FILTER_CALLBACK过滤器。您可以返回bool甚至添加openRange参数。还有一个好处:您可以使用其他功能,例如检查每个数组数或POST / GET值的范围。那是非常强大的工具。


2

使用比较运算符比调用任何函数要快得多。我不确定这是否存在,但我认为不是100%。


确实,使用比较运算符比调用函数要快,因为函数在PHP中很慢。另一方面,它只是一个独立的函数,避免每次都重复运算符。中间的方法可以是某些其他语言(例如C,C ++或Rust)中的Macro。但是PHP没有此功能,也没有内置的“之间”函数,因此使用该函数必须创建该函数,或者如答案中所述使用“ filter_var”,即使在这种情况下“ filter_var”为不太方便写。
AnthonyB

1

您可以in_array()结合使用range()

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

注意但是正如注释中指出的那样,如果您专注于性能,那么这并不是一个很好的解决方案。生成数组(尤其是较大范围的数组)会减慢执行速度。


2
@Yukulélé问题是:如何检查INTEGER是否在范围内?
彼得

看到我对星云座的回答。
Patrick Allaert

3
这个想法很有趣并且易于理解,但是使用这种方法的性能很差。
AnthonyB

我认为这是一个不错的选择,感谢您的理解。因此,我删除了我的反对意见。
AnthonyB
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.