Utilisation des opérateurs sur les bits en PHP



Documents pareils
Chapitre 1 I:\ Soyez courageux!

Introduction à MATLAB R

Programmation C++ (débutant)/instructions for, while et do...while

V- Manipulations de nombres en binaire

Représentation d un entier en base b

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

Architecture des ordinateurs TD1 - Portes logiques et premiers circuits

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C

Les portes logiques. Voici les symboles des trois fonctions de base. Portes AND. Portes OR. Porte NOT

Le stockage local de données en HTML5

Cours d initiation à la programmation en C++ Johann Cuenin

Cours Informatique Master STEP

I. Introduction aux fonctions : les fonctions standards

Arithmétique binaire. Chapitre. 5.1 Notions Bit Mot

Notions fondamentales du langage C# Version 1.0

Programmation Objet - Cours II

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Une version javascript sera disponible directement dans le cours prochainement.

La mémoire. Un ordinateur. L'octet. Le bit

CONCOURS DE L AGRÉGATION INTERNE «ÉCONOMIE ET GESTION» SESSION 2015 SECONDE ÉPREUVE

LES DÉTERMINANTS DE MATRICES

Licence Sciences et Technologies Examen janvier 2010

COURS WINDEV NUMERO 3

Initiation à la programmation en Python

Compte-rendu de projet de Système de gestion de base de données

Définition 0,752 = 0,7 + 0,05 + 0,002 SYSTÈMES DE NUMÉRATION POSITIONNELS =


1. Introduction Création d'une macro autonome Exécuter la macro pas à pas Modifier une macro... 5

AWS avancé. Surveiller votre utilisation d EC2

Reporting Services - Administration

Les arbres binaires de recherche

les Formulaires / Sous-Formulaires Présentation Créer un formulaire à partir d une table...3

Projet ISN - dossier réalisé par Randrianarimanana Stéphanie. Titre du projet : Site de rencontre. le nom de notre site de rencontre : Linkymeet

Recherche dans un tableau

Algorithme. Table des matières

Module 16 : Les fonctions de recherche et de référence

Corrigé des TD 1 à 5

UFR de Mathématiques et Informatique Année 2009/2010. Réseaux Locaux TP 04 : ICMP, ARP, IP


La fonction exponentielle

Systèmes de transmission

Pluridisciplinarité. Classe de BTS DATR

ALGORITHMIQUE ET PROGRAMMATION En C

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Création d'un site dynamique en PHP avec Dreamweaver et MySQL

SHERLOCK 7. Version du 01/09/09 JAVASCRIPT 1.5

Algorithmique et Programmation, IMA

Cours 1 : La compilation

Initiation à l algorithmique

Complexité. Licence Informatique - Semestre 2 - Algorithmique et Programmation

CREG : versailles.fr/spip.php?article803

Organigramme / Algorigramme Dossier élève 1 SI

Diviser un nombre décimal par 10 ; 100 ; 1 000

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Trier les ventes (sales order) avec Vtiger CRM

LES TYPES DE DONNÉES DU LANGAGE PASCAL

Stockage du fichier dans une table mysql:

Rafraichissement conditionné d'une page en.net

BTS S.I.O PHP OBJET. Module SLAM4. Nom du fichier : PHPRévisionObjetV2.odt Auteur : Pierre Barais

TP : Shell Scripts. 1 Remarque générale. 2 Mise en jambe. 3 Avec des si. Systèmes et scripts

Programmation linéaire

Les suites numériques

ACTIVITÉ DE PROGRAMMATION

Couche application. La couche application est la plus élevée du modèle de référence.

Introduction au langage C

Les opérations binaires

Les structures de données. Rajae El Ouazzani

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

Logiciel de Base. I. Représentation des nombres

Date M.P Libellé Catégorie S.Catégorie Crédit Débit Solde S.B

Mysql. Les requêtes préparées Prepared statements

TP 2 Réseaux. Adresses IP, routage et sous-réseaux

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Création et Gestion des tables

CONCEPTION Support de cours n 3 DE BASES DE DONNEES

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Utilisation d objets : String et ArrayList

LES TOUT PREMIERS PAS

1 Gestionnaire de Données WORD A4 F - USB / / 6020 Alco-Connect

Télécom Nancy Année

Le prototype de la fonction main()

La conversion de données : Convertisseur Analogique Numérique (CAN) Convertisseur Numérique Analogique (CNA)

ET 24 : Modèle de comportement d un système Boucles de programmation avec Labview.

Bases de programmation. Cours 5. Structurer les données

Utilisation du BDE pour la maintenance des fichiers DBF de l'application TopoCad:

1. Introduction Création d'une requête...2

Base de l'informatique. Généralité et Architecture Le système d'exploitation Les logiciels Le réseau et l'extérieur (WEB)

Calculateur quantique: factorisation des entiers

Conversion d un entier. Méthode par soustraction

Cours 1 : Qu est-ce que la programmation?

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

Comment ranger automatiquement les messages qui m'arrivent, grâce à et dans Thunderbird seulement.

Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application

Projet d informatique M1BI : Compression et décompression de texte. 1 Généralités sur la compression/décompression de texte

Stocker des données sur Amazon S3

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

Transcription:

Introduction Comme vous le savez sans doute, un processeur ne connaît ni les nombres entiers ni les nombres réels, ni les chaînes de caractères. La seule chose que votre processeur sait traiter ce sont des bits (binary digit) bref des niveaux électriques. Comme en C, il existe en PHP des opérateurs qui permettent de manipuler directement ces bits contenus dans les variables avec lesquelles nous travaillons quotidiennement en PHP. Pourquoi, me direz vous utiliser ces opérateurs peu attrayants? Eh bien pour les performances. Ils permettent en effet, d'améliorer les performances de leurs scripts en limitant au maximum le nombre d'étapes nécessaires pour parvenir à des instructions compréhensibles par le processeur. Tous les opérateurs sur les bits correspondent à des instructions directement compréhensibles par votre processeur. Bref, ils permettent de mâcher le boulot de l'interpréteur, (pour les langages de scripts ex : PHP) ou des compilateurs pour les langages compilés (C/C+). Rappel de notions élémentaires : comme nous allons manipuler des bits il est important que vous compreniez la notions de poids des bits dans une variable. Le poids d'un bit c'est un peu l'indice de sa position dans le tableau de bit que constitue la variable. 1.2 Exemple En binaire, l'entier 3 s'écrit 00000011 et 2 s'écrit 00000010 $a=3; $b=2; $c=$a^$b; $a vaudra 3 soit en binaire 00000011 $b vaudra 2 soit en binaire 00000010 $c vaudra 1 soit en binaire 00000001 On s'aperçoit ici que si $a égale $b, $c vaudra 0. On peut donc trouver une écriture alternative à cette phrase : if($a!=$b) die("\\$a est différents de \\$b" En utilisant Xor on a : if($a^$b) die("\\$a est différents de \\$b" Si $a=18 (00010010) les bits à 1 sont les bits de poids 1 et 4. Poids 7 6 5 4 3 2 1 0 Bits de $a 0 0 0 1 0 0 1 0 $a se calcule donc de la façon suivante : $a=1*pow(2,4)+1*pow(2,1 ou $a=1*16+1*2; Présentation des divers opérateurs 2 AND (&) 2.1 Introduction Le résultat d'un & entre $a et $b est le suivant : chaque fois que 1 bit de $a, est à 1 en même temps que celui de $b, le résultat retourné voit son bit de même poids passer à 1. 2.2 Exemple En binaire, l'entier 3 s'écrit 00000011 et 2 s'écrit 00000010 1 XOR (^) 1.1 Introduction Le résultat d'un Xor entre $a et $b est le suivant : chaque fois que 1 bit de $a ne correspond pas au bit de $b de même poids, le résultat retourné voit son bit de même poids passé à 1. NB :On ne prendra en compte que les 8 bits de poids faible de l'entier qui est lui codé sur 32 bits (31 + un bit de signe) $a=3; $b=2; $c=$a&$b; $a vaudra 3 soit en binaire 00000011 $b vaudra 2 soit en binaire 00000010 $c vaudra 2 soit en binaire 00000010 08/16/02 1

3 OR ( ) 3.1 Introduction Le résultat d'un entre $a et $b est le suivant : chaque fois que 1 bit de $a ou de $b est à 1, le résultat retourné voit son bit de même poids passé à 1. 3.2 Exemple 5.2 Exemple $a=5; // 00000101 en binaire $b=$a<<1; $c=$b<<3; En binaire l'entier 5 s'écrit 00000101 et 3 s'écrit 00000011 Donc si on a: $a=5; $b=3; $c=$a $b; $a vaudra 5 soit en binaire 00000101 $b vaudra 3 soit en binaire 00000011 $c vaudra 7 soit en binaire 00000111 4 NOT (~) 4.1 Introduction $a vaudra 5 soit 00000101 en binaire $b vaudra 10 soit 00001010 en binaire $c vaudra 80 soit 01010000 en binaire Remarquez que chaque décalage correspond à une multiplication par 2 de la valeur. 6 Décalage à droite (>>) 6.1 Introduction Cet opérateur permet de décaler les bits d'une variable n fois vers la droite. Le résultat de l'opération correspond non pas aux bits qui sont sorti mais ceux qui sont restés. Les bits insérés (à gauche) valent tous 0. 6.2 Exemple Le résultat d'un ~ sur la variable $a retourne un strict complément à 1 de $a c'est à dire que chaque bit de $a qui était à 1 passe à 0 et réciproquement. 4.2 Exemple Donc si on a: $a=53; $b=~$a; $a=5; // 00000101 en binaire $b=$a>>2; $a vaudra 5 soit 00000101 en binaire $b vaudra 1 soit 00000001 en binaire Remarquez que chaque décalage correspond à une division entière par 2 de la valeur. $a vaudra 00000000 00000000 00000000 00110101 soit 53 $b vaudra 11111111 11111111 11111111 11001010 soit 54 5 Décalage à gauche (<<) 5.1 Introduction Cet opérateur permet de décaler les bits d'une variable n fois vers la gauche. Le résultat de l'opération correspond non pas aux bits qui sont sorti mais ceux qui sont restés. Les bits insérés (à droite) valent tous 0. Globalis Media Systems Siège social : 75, rue de Lourmel 75015 Paris. Bureaux et correspondance : 25, rue Thiboumery 75015 Paris infos@globalis ms.com http://www.globalis ms.com 08/16/02 2

Quelques exemples didactiques Laissons de coté (pour un temps) les considérations de performances et voyons des exemples un peu complexes d'utilisation de ces opérateurs. 1 Addition de deux entiers quelconques Rappel pour ceux qui ne sont pas des familiers de la base 2. Lorsqu'on effectue une addition à la main en base 10 (comme en primaire) on calcule de la façon suivante : 012 +129 =141 9+2=11 je pose 1 et je retiens 1 1+2+1(retenue)=4 0+1=1 on a alors le résultat escompté (141) En binaire le fonctionnement est a peu près similaire : 3+1 nous donne 0000 0011 (3) +0000 0001 (1) =0000 0100 (4) Le raisonnement est le suivant : 1+1=10 je pose 0 et je retiens 1, 1+0+1(retenue)=0 je pose 0 et je retiens 1, 0+0+1(retenue)=1 La fonction ci dessous effectue une addition des deux valeurs qui lui sont fournie en paramètres : plus(11,14 Appel de la fonction function plus($a,$b) $a==11 (0000 1011) $b==14 (0000 1110) $test = $a; $test==11 (0000 1011) $a ^= $b; $a==5 (0000 0101) $test==10 (0000 1010) // Où sont $test <<= 1; $test==20 (0001 0100) // Décalage des retenues $b = $test; $b==20 (0001 0100) $test est non null donc on reprend la boucle $test = $a; $test==5 (0001 0100) $a ^= $b; $a==17 (0001 0001) $test <<= 1; $test==4 (0000 0100) // Où sont $test==8 (0000 1000) // Décalage des retenues $b = $test; $b==8 (0000 1000) $test est non null donc on reprend la boucle $test = $a; $test==17 (0001 0100) $a ^= $b; $a==25 (0001 1001) $test <<= 1; $test==0 (0000 0000) // Où sont $test==0 (0000 0000) // Décalage des retenues $b = $test; $b==0 (0000 0000) $test==0 (il n'y a plus de retenues) donc on sort de la boucle return $a // ON renvoit $a donc 25 (11+14) function plus($a,$b) { do { $test = $a; $a ^= $b; // Où sont $test <<= 1; // Décalage des retenues $b = $test; // Propagation des retenues while ($test // retenues? return $a; Pour mieux comprendre le fonctionnement de la fonction suivons l'évolution des variables lors de l'appel de cette fonction avec les paramètres suivants $a=11 et $b=14 08/16/02 3

2 Multiplication de deux entiers quelconques Attaquons nous maintenant à la multiplication nous utiliserons lorsque nous en auront besoin la fonction plus($a,$b) que nous avons détaillé plus haut. function mul($a,$b) { $res = 0 ; $i = 0; while($b) { // Teste la valeur du bit de poids // le plus faible de $b if($b & 1) { $tmp = $a << $i; // $tmp=pow(2,$i $res=plus($res,$tmp // $res+=$tmp; // Décalage de $b en vue de tester //le bit suivant $b >>= 1; // Incrémentation de $i en vue de garder // une trace du poids du bit testé ensuite $i = plus($i,1 return $res; Le principe est le suivant, pour ne pas avoir à bouclé 6 fois sur $res+=3; algorithme certes fonctionnel mais bon le temps d'exécution serait proportionnel à la valeur du multiplicateur. Nous allons faire mieux. Pour cela nous allons chercher les puissances de 2 qui composent le multiplicateur ($b) multiplier $a par chacune de ces puissance de 2. Puis faire la sommes des résultats obtenus. Pour mieux comprendre le fonctionnement de la fonction, suivons l'évolution des variables lors de l'appel de cette fonction avec les paramètres suivants $a=3 et $b=6 mul(3,6 Appel de la fonction function mul($a,$b) $a==3 (0000 0011) if($b&1){ $tmp=$a<<$i; $res=plus($res,$tmp $b==1 $tmp=$i; $i=plus($i,1 if($b&1){ $tmp=$a<<$i; $b==3 (0000 0011) On reboucle $b&1 est vrai $a==3, $i==1, donc $tmp==6 $i==2 $res=plus($res,$tmp $res==18 $b>>=1; $i=plus($i,1 return $res; $b==1 (0000 0001) On reboucle $b&1 On rentre dans le if $a==3, $i==2, donc $tmp==12 $b==0 $i==3 $b==0 (0000 0000) On sort de la boucle On renvoie le résultat escompté 18 Quelques exemples concrets 1 Gestion d'articles sur deux colonnes Prenons comme premier exemple la problématique suivante. Imaginons que nous ayons une liste d'articles à afficher sur deux colonnes. Et que nous souhaitions équilibrer le nombre d'articles dans les deux colonnes. Dans notre exemple il y aura 11 articles, on souhaitera donc en avoir 6 dans la colonne de gauche et 5 dans celle de droite. Une approche classique serait la suivante : $nb_articles=11; $nb_a_gauche = $nb_articles/2; $nb_a_gauche = ceil($nb_a_gauche $nb_a_droite = $nb_articles $nb_a_gauche; $res=0 ; $b==6 (0000 0110) $res==0;(0000 0000) La nôtre toujours destinée à présenter les opérateurs sur les bits, sera sensiblement différente : $i=0; if ($b&1){ $i==0; (0000 0000) $b==6 (0000 0110) On entre dans la boucle $b & 1 est faux. On ne rentre pas dans le if $b >>= 1; $b==3 (0000 0011) Décalage de $b en vue de tester le bit de poids supérieur $b $i = plus($i,1 $i==1 $nb_articles=11; // permet de récupéré le résultat de la // division entière par 2 $nb_a_gauche = $nb_articles >> 1; // Permet de gérer le cas de d'un nombre impair if($nb_articles & 1) $nb_a_gauche++; $nb_a_droite = $nb_articles $nb_a_gauche; A titre d'information d'après les tests de performance que j'ai pu faire en bouclant 10000 fois sur chacun des deux scripts, j'ai observé que le second script mettait environ 10% de temps en moins pour s'exécuter. 08/16/02 4

2 Contrôle de droits d'accès d'un utilisateur Imaginons une problématique de contrôle d'accès à des pages. Problématique somme toute assez courante. Admettons que vous ayez quatre pages sur votre site WEB et un menu pour y accéder. Après authentification de votre utilisateur, vous récupérez ses droits d'accès. Vous pourriez stocker ses droits dans un fichier PHP contenant les informations suivantes et dont vous feriez une inclusion. // fichier de droits de l'utilisateur $page1= "OK"; $page2= "NON"; $page3= "OK"; $page4= "OK"; Puis traiter ses différentes chaînes pour afficher ou non le menu. En faisant des tests comme ceux ci. if($page1=="ok") echo "<a href=page1.php>page1</a><br>"; if($page2=="ok") echo "<a href=page2.php>page2</a><br>"; if($page3=="ok") echo "<a href=page3.php>page3</a><br>"; if($page4=="ok") echo "<a href=page4.php>page4</a><br>"; Mais vous pouvez aussi stocker ces informations d'une autre façon. // fichier de droits de l'utilisateur $droits_user =13; // 13 vaut 00001101 en binaire ce qui signifie dans // notre formalisme que l'utilisateur actuel a // le droit de voir les pages 1,3,4 Et traiter cette information de la façon suivante $masque=1; $i=1; for ($i=1;$i<5;$i++) { if ($droits_user & $masque) { echo "<a href=page$i.php>page$i</a><br>"; // Multiplication par 2 de $masque pour tester // si le bit suivant est à 1 $masque <<= 1; 3 Contrôle de droits avec gestion de groupe Maintenant imaginons que notre application est un peu plus compliquée et les utilisateurs obtiennent leur droits via les groupes auxquels ils appartiennent. L'utilisateur n'a donc plus de droits propres. // Groupes de l'utilisateur $groupe = array( 'redacteur'=> "OK", 'admin'=>"non", 'relecteur'="ok" // Droits rédacteur 'page1'=>"ok", 'page2'=>"non", 'page3'=>"ok", 'page4'=>"non" // Droits administrateur 'page1'=>"ok", 'page2'=>"ok", 'page3'=>"ok", 'page4'=>"ok" // Droits relecteur 'page1'=>"ok", 'page2'=>"non", 'page3'=>"non", 'page4'=>"ok" Notre Utilisateur a donc les droits de voir les pages 1,3,4. Vous pressentez ici que les tests qui vont permettre l'affichage des liens deviennent beaucoup plus complexes. Utilisons maintenant le même principe que précédemment. // Groupes de l'utilisateur $groupes = 5; // 00000101 $page_redacteur = 5; // Droits rédacteur $page_admin = 15; // Droits administrateur $page_relecteur=9; // Droits relecteur // On récupère les droits des groupes de l'utilisateur // en incluant les bons fichiers de droits, puis on // calcule les droits de l'utilisateur obtenu via // les groupes en faisant $droits_user=$page_redacteur; // 00000101 $droits_user =$page_relecteur; // 00000101 ou 00001001 // =00001101 // Enfin on affiche les pages correspondantes $masque = 1; $i = 1; for($i=1;$i<5;$i++) { if(droits_userecho "<a href=page$i.php>page$i</a><br>"; // Multiplication par 2 de $masque pour tester // si le bit suivant est à 1 $masque <<= 1; / Notre formalisme permet de récupérer, en très peu d'opérations, la résultante des droits de l'utilisateur et de l'exploiter de la même manière que précédemment. Conclusion Comme nous venons de le voir, il est possible de faire une utilisation intelligente des opérateurs sur les bits. Cependant, il est relativement difficile de faire une estimation du gain en terme de performances. Néenmoins, comme nous avons pu le constater dans les deux derniers exemples, ils présentent un intérêt fonctionnel réel. Ils ont aussi l'avantage de familiariser un tant soit peu les développeurs avec les couche basse de la programmation. olivier.huet@globalis ms.com 08/16/02 5