web-dev-qa-db-fra.com

Comment vérifier si un entier est dans une plage?

Existe-t-il un moyen de tester une plage sans utiliser ce code redondant:

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

?

Comme une fonction:

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

usage:

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

?

Est-ce que PHP a une telle fonction intégrée? Ou tout autre moyen de le faire?

66
dynamic

Je ne pense pas que vous obtiendrez un meilleur moyen que votre fonction.

Il est propre, facile à suivre et à comprendre, et renvoie le résultat de la condition (no return (...) ? true : false mess).

47
alex

Testez vos 3 manières avec une boucle de 1000000 fois.

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 était le plus rapide, c'était essentiellement ceci:

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

Il n'y a pas de fonction intégrée, mais vous pouvez facilement y arriver en appelant les fonctions min() et max() correctement.

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

La plupart des exemples donnés supposent que, pour la plage de test [$ a .. $ b], $ a <= $ b, c’est-à-dire que les extrêmes de la plage sont dans l’ordre inférieur - supérieur et la plupart supposent que tous sont des nombres entiers.
Mais il me fallait une fonction pour tester si $ n était entre $ a et $ b, comme décrit ici:

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

All numbers can be real, not only integer.

Il existe un moyen facile de tester.
Je base le test sur le fait que ($n-$a) et ($n-$b) ont des signes différents lorsque $ n est compris entre $ a et $ b, et le même signe lorsque $ n est en dehors de la plage $ a.. $ b.
Cette fonction est valable pour tester des nombres croissants, décroissants, positifs et négatifs, sans se limiter à tester uniquement des nombres entiers.

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

Je ne peux pas commenter (pas assez de réputation) alors je vais modifier la réponse de Luis Rosety ici:

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

Cette fonction fonctionne également dans les cas où n == a ou n == b.

Preuve: Que n appartienne à la plage [a, b], où [a, b] est un sous-ensemble de nombres réels.

Maintenant a <= n <= b. Alors n-a> = 0 et n-b <= 0. Cela signifie que (n-a) * (n-b) <= 0.

Le cas b <= n <= a fonctionne de la même manière.

6
Esa Lindqvist

Il y a aussi filter_var() et c'est la fonction native qui vérifie l'étendue . Cela ne donne pas exactement ce que vous voulez (ne retourne jamais de vrai), mais avec "triche", nous pouvons le changer.

Je ne pense pas que ce soit un bon code quant à la lisibilité, mais je montre que c'est une possibilité:

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

Il suffit de remplir $someNumber, $min Et $max. filter_var Avec ce filtre renvoie soit booléen false si le nombre est en dehors de la plage, soit le nombre lui-même lorsqu'il est dans la plage. L'expression (!== false) Fait que la fonction renvoie la valeur true lorsque le nombre est dans la plage.

Si vous voulez le raccourcir d'une manière ou d'une autre, souvenez-vous de la transposition de caractères. Si vous utilisiez !=, Il serait faux pour le nombre 0 dans la plage -5; +5 (alors que cela devrait être vrai). La même chose se produirait si vous utilisiez le transtypage ((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]])) ...

Imaginez que (d'une autre réponse):

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

Si l'utilisateur écrivait une valeur vide ($userScore = ''), Elle serait correcte, car in_array Est défini ici comme valeur par défaut, non plus strict et cela signifie que la plage crée également 0 et '' == 0 (non strict), mais '' !== 0 (si vous utilisiez le mode strict). C'est facile de rater de telles choses et c'est pourquoi j'ai écrit un peu à ce sujet. On m'a appris que les opérateurs stricts sont les opérateurs par défaut et que le programmeur ne peut utiliser le non-strict que dans des cas particuliers . Je pense que c'est une bonne leçon. La plupart des exemples ici échoueraient dans certains cas en raison d'une vérification non stricte.

Néanmoins, j'aime bien filter_var et vous pouvez utiliser les fonctions ci-dessus (ou ci-dessous si j'avais eu une telle "ascension";)) et faire votre propre rappel que vous utiliseriez comme filtre FILTER_CALLBACK. Vous pouvez retourner bool ou même ajouter le paramètre openRange. Et autre bon point: vous pouvez utiliser autres fonctions , par exemple. plage de vérification de chaque nombre de valeurs de tableau ou de POST/GET. C'est un outil vraiment puissant.

3
Krzysiu

L'utilisation d'opérateurs de comparaison est beaucoup plus rapide que d'appeler une fonction. Je ne suis pas sûr à 100% si cela existe, mais je pense que non.

2
Thom Wiggers

Vous pouvez le faire en utilisant in_array() combiné avec range()

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

Note Comme cela a été souligné dans les commentaires, ce n’est pas vraiment une bonne solution si vous vous concentrez sur la performance. La génération d'un tableau (particulièrement avec des plages plus grandes) ralentira l'exécution.

0
Peter