43 votes

Pourquoi in_array() renvoie-t-il à tort true avec ces chaînes de caractères (à gros chiffres) ?

Je ne comprends pas ce qui ne va pas avec ce code. Il renvoie "Found", alors qu'il ne devrait pas.

$lead = "418176000000069007";
$diff = array("418176000000069003","418176000000057001");

if (in_array($lead,$diff))
    echo "Found";
else
    echo "Not found";

1 votes

J'ai obtenu Not Found sur PHP 5.3.6-13ubuntu3.6 avec Suhosin-Patch (cli) (construit : Feb 11 2012 03:26:01) (Linux Mint, mais je ne pense pas que cela importe). Comment essayez-vous de l'exécuter ? Environnement ? CLI/GCI ?, etc...

78 votes

3 votes

Pouvez-vous le reproduire avec des chiffres qui ne sont pas des chiffres ?

140voto

Mark Reed Points 23817

Note : ce comportement a été modifié en PHP 5.4.

Par défaut, in_array utilise une comparaison libre ( == ), ce qui signifie que les chaînes de caractères numériques sont converties en nombres et comparées comme des nombres. Avant PHP 5.4, si vous n'aviez pas assez de précision dans le type de virgule flottante de votre plate-forme, la différence était perdue et vous obteniez une mauvaise réponse.

Une solution consiste à activer strict comparaison ( === ) en passant un Boolean pour in_array :

  $lead = "418176000000069007";
  $diff = array("418176000000069003", "418176000000057001");

  if ( in_array($lead, $diff, true) ) 
    echo "Found";
  else
    echo "Not found";

Ensuite, les chaînes de caractères sont comparées comme des chaînes de caractères, sans coercition numérique. Cependant, cela signifie que vous perdez l'équivalence par défaut de chaînes comme "01234" et "1234".

Ce comportement a été signalé comme un bogue et corrigé en PHP 5.4. Les chaînes numériques sont toujours converties en nombres lorsqu'elles sont comparées à == mais seulement si la valeur de la chaîne correspond au type numérique de la plate-forme.

1 votes

Pour autant que je sache, == ne convertit pas les chaînes de caractères en nombres. Il convertit les types s'ils sont différents, mais comparer deux chaînes de caractères n'est pas, à mon avis, une bonne idée.

12 votes

@gavriel : ce n'est malheureusement pas vrai ; si une chaîne de caractères ressemble à un nombre, elle est convertie en un. Ajoutez quelques zéros pour qu'une comparaison numérique perde en précision même sur votre installation 64 bits, et c'est facile à démontrer : php -r 'echo("4181760000000000069003" == "4181760000000000057001"),"\n";' retourne 1.

1 votes

Donc, à votre avis, $lead = "001" ; $arr = array("1", "01") ; echo in_array($lead, $arr) ; devrait retourner true ?

56voto

arun Points 2360

Note : Il s'agissait d'un bogue dans les anciennes versions de PHP. PHP 5.4 et des versions plus récentes.

C'est à cause des limitations du stockage des nombres dans PHP

Le vrai problème ici est qu'à cause de la PHP_INT_MAX - la valeur dépassée dans notre cas.

Essayez de echo / print_r $lead y $diff sans utiliser les guillemets. Il en résultera

$lead ---> 418176000000070000  
$diff ---> Array ( [0] => 418176000000070000 [1] => 418176000000060000 )

donc, dans ce cas, le in_array Le résultat est vrai !

donc utiliser strict comparaison dans in_array() en fixant le troisième argument dans in_array() comme true

     if(in_array($lead,$diff,true)) //use type too
       echo "Found";
     else
       echo "Not found";
?>

Essayez ceci. Ça va marcher.

16voto

nauphal Points 4328

C'est à cause d'un défaut de PHP. 418176000000069007 est modifié en 2147483647 (limite entière de PHP). C'est pourquoi vous obtenez Found .

essayez in_array($lead, $diff, true)

If the third parameter strict is set to TRUE then the in_array() 
function will also check the types of the needle in the haystack.

0 votes

Ohhh...mon dieu...j'ai presque essayé toutes les combinaisons...de toute façon, y a-t-il une solution ? ?

9 votes

La question est de savoir pourquoi il le lance dans un int du tout ?

3 votes

@Amit Set $strict a true : in_array($lead, $diff, true)

6voto

web-nomad Points 3632

Les valeurs dépassent PHP_INT_MAX . Essayez de faire if(in_array($lead,$diff,true)) à la place.

5voto

ieatbytes Points 56

in_array doivent être limitées.

$lead = "418176000000069007";
  $diff = array("418176000000069003","418176000000057001");

  if(in_array($lead,$diff,true)) 
    echo "Found";
  else
    echo "Not found";

Ce problème est dû à vos chiffres sont dépassés par rapport à la limite d'entiers définie

Remarque : la valeur maximale dépend du système. Les systèmes 32 bits ont une plage maximale d'entiers signés de -2147483648 a 2147483647 . Donc par exemple sur un tel système, intval('1000000000000') retournera 2147483647 . La valeur maximale des entiers signés pour les systèmes 64 bits est de 9223372036854775807 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X