PHP est faiblement typé !

A votre avis, que retourne le code suivant :

var_dump('11111111111111111' == '11111111111111112');
var_dump('11111111111111111' === '11111111111111112');
var_dump(11111111111111111 === 11111111111111112);
var_dump(11111111111111111 == 11111111111111112);

Et en bonus :

var_dump('12abc' == 12); 

On serait tenté de dire : c'est simple "faux" !

Et bien non..

boolean true
boolean false
boolean true
boolean true
boolean true

Comment est ce possible ?

Et bien deux raisons à cela ?

La première est que PHP est faiblement typé donc sauf à lui demander de comparer strictement (cas 2) nos deux chaines de caractères comme des chaines de caractères et bien PHP va les transtyper en double.

La seconde, vous m'avez vu venir avec mes gros sabots : je vous ai dit double et bien les doubles sont codés sur 8 octets (55 bits + 1 de parité) donc nos valeurs dépassent l'espace mémoire alloué la comparaison se fait donc sur un bit en moins.

La preuve ?

// Comparons deux valeurs codés sur 55 bits 
//18014398509481983 == 3FFFFFFFFFFFFF (hexa) == 111111111111111111111111111111111111111111111111111111 (binaire)

var_dump('18014398509481982' == '18014398509481983'); // false
var_dump('18014398509481982' === '18014398509481983'); // false
var_dump(18014398509481982 === 18014398509481983); // false
var_dump(18014398509481982 == 18014398509481983); // false

// Et maintenant une sur 55 et une sur 56 bits
// 18014398509481984 == 40000000000000 (hexa) == 1000000000000000000000000000000000000000000000000000000 (binaire)

var_dump('18014398509481983' == '18014398509481984'); // true
var_dump('18014398509481983' === '18014398509481984'); // false
var_dump(18014398509481983 === 18014398509481984); // true
var_dump(18014398509481983 == 18014398509481984); // true

Morale de l'histoire ?

Faire très attention lorsque l'on fait des comparaisons en PHP ou que l'on manipule des valeurs très grandes, on peut obtenir des cas surprenant. L'opérateur de comparaison stricte ne doit pas être négligé.

Pour la petite histoire : ce billet m'est venu d'une discussion sur la liste de diffusion "internals" de PHP à propos d'une implémentation, envisagée puis annulée; du typage des scalaires (int, string). Je vous renvois à la RFC proposé par Zeev Suraski à ce sujet "Strict and weak parameter type checking" (voir les tables de transtypage).

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

La discussion continue ailleurs

URL de rétrolien : http://www.au-fil-du.net/trackback/156

Fil des commentaires de ce billet