begin process at 2012 05 27 20:47:58
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > UTILISATION INTELLIGENTE DES VARIABLES GLOBALES ...

UTILISATION INTELLIGENTE DES VARIABLES GLOBALES ...


 Information sur la source

Note :
9,8 / 10 - par 5 personnes
9,80 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Astuces Niveau :Initié Date de création :16/10/2004 Date de mise à jour :17/10/2004 17:06:22 Vu :5 225

Auteur : LocalStone

Ecrire un message privé
Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note

 Description

Salut à tous,
Ce code n'est pas vraiment un code à proprement parlé, mais plutôt une ébauche de tutoriel visant à expliquer l'interêt d'utilisation des variables globales. Je poste ça sur PHPCS parce que c'est un peu le seul langage que je connaisse vraiment bien, mais ce tutoriel est en fait valable pour l'integralité des langages de programmation existant.
Les variables globales servent souvent pour enregistrer des variables d'environnement que des classes ou des fonctions pourront récuperer et utiliser, voire modifier. Mais il existe également une autre utilisation de ces variables.
Elles peuvent en effet servir à optimiser certaines fonctions basée sur des boucles. Pour exemple, je vais utiliser 3 fonctions qui permettent de calculer le factoriel d'un entier n (rappel : n! = 1 * 2 * 3 * ... (n - 1) * (n). Pour info, ça peut aussi bien servir dans les probabilités que dans l'approximation de Pi ou de l'exponentiel ...).
La première fonction (factoriel_1) est récursive : elle s'appelle elle-même. J'ai pas trop la pédagogie nécessaire pour expliquer, alors je vous laisse comprendre .... Désolé. Mais c'est pas compliqué à comprendre !
La seconde fonction (factoriel_2) est barbare (dans le sens de "barbare logiquement"). Elle va calculer le factoriel à l'aide d'une boucle for, en multipliant une variable par elle même, etc ... Pareil, pas très compliqué à comprendre, c'est une fonction intuitive puisqu'elle suit notre pensée.
Enfin, la troisième fonction (factoriel_3) utilise les variables globales ...

Source

  • <?php
  • // La fonction factorielle récursive ...
  • function factoriel_1($n)
  • {
  • if ($n == 0)
  • {
  • return(1);
  • }
  • else
  • {
  • return($n * factoriel_1($n - 1));
  • }
  • }
  • // La fonction factorielle itérative...
  • function factoriel_2($n)
  • {
  • $factoriel = 1;
  • for ($i = 1; $i <= $n; $i++)
  • {
  • $factoriel *= $i;
  • }
  • return($factoriel);
  • }
  • // La fonction factorielle optimisée ...
  • // On déclare d'abord le tableau qui va devenir global. Il contient en fait le résultat de 0! (factoriel de 0) = 1.
  • $_factoriel = array('input' => 0, 'output' => 1);
  • function factoriel_3($n)
  • {
  • // On rend le tableau global ...
  • global $_factoriel;
  • // On regarde pour voir si la demande est la même que celle du tableau.
  • if ($n == $_factoriel['input'])
  • {
  • // Si oui, on set la variable qui va être retournée avec la valeur du tableau global.
  • $factoriel = $_factoriel['output'];
  • }
  • // On regarde maintenant si on va gagner du temps en utilisant le tableau global.
  • elseif (abs($n - $_factoriel['input']) < $n)
  • {
  • // Si oui, les blocs suivants vont déterminés s'il faut décrémenter ou incrémenter pour acceder au factoriel voulu.
  • $factoriel = $_factoriel['output'];
  • if ($n - $_factoriel['input'] > 0)
  • {
  • for ($i = $_factoriel['input'] + 1; $i <= $n; $i++)
  • {
  • $factoriel = $factoriel * $i;
  • }
  • }
  • else
  • {
  • for ($i = $_factoriel['input']; $i >= $n + 1; $i--)
  • {
  • $factoriel = $factoriel / $i;
  • }
  • }
  • }
  • // Si ça ne vaut pas le coup, on calcule le factoriel de manière primaire.
  • else
  • {
  • $factoriel = 1;
  • for ($i = 1; $i <= $n; $i++)
  • {
  • $factoriel *= $i;
  • }
  • }
  • // On update les globales pour l'utilsation suivante de la fonction.
  • $_factoriel['input'] = $n;
  • $_factoriel['output'] = $factoriel;
  • return($factoriel);
  • }
  • ?>
<?php
	// La fonction factorielle récursive ...
	function factoriel_1($n)
	{
		if ($n == 0)
		{
			return(1);
		}
		else 
		{ 
			return($n * factoriel_1($n - 1));
		}
	}
	// La fonction factorielle itérative...
	function factoriel_2($n)
	{
		$factoriel = 1;
		for ($i = 1; $i <= $n; $i++)
		{
			$factoriel *= $i;
		}
		return($factoriel);
	}
	// La fonction factorielle optimisée ...
	// On déclare d'abord le tableau qui va devenir global. Il contient en fait le résultat de 0! (factoriel de 0) = 1.
	$_factoriel = array('input' => 0, 'output' => 1);	
	function factoriel_3($n)
	{
		// On rend le tableau global ...
		global $_factoriel;
		// On regarde pour voir si la demande est la même que celle du tableau.
		if ($n == $_factoriel['input'])
		{
			// Si oui, on set la variable qui va être retournée avec la valeur du tableau global.
			$factoriel = $_factoriel['output'];
		}
		// On regarde maintenant si on va gagner du temps en utilisant le tableau global.
		elseif (abs($n - $_factoriel['input']) < $n)
		{
			// Si oui, les blocs suivants vont déterminés s'il faut décrémenter ou incrémenter pour acceder au factoriel voulu.
			$factoriel = $_factoriel['output'];
			if ($n - $_factoriel['input'] > 0)
			{ 
				for ($i = $_factoriel['input'] + 1; $i <= $n; $i++)
				{
					$factoriel = $factoriel * $i;
				}
			}
			else 
			{
				for ($i = $_factoriel['input']; $i >= $n + 1; $i--)
				{
					$factoriel = $factoriel / $i;
				}
			}
		}
		// Si ça ne vaut pas le coup, on calcule le factoriel de manière primaire.
		else
		{
			$factoriel = 1;
			for ($i = 1; $i <= $n; $i++)
			{
				$factoriel *= $i;
			}
		}
		// On update les globales pour l'utilsation suivante de la fonction.
		$_factoriel['input'] = $n;
		$_factoriel['output'] = $factoriel;
		return($factoriel);
	}

?>

 Conclusion

Bon, comme les fonctions sont mal expliquées, j'explique l'idée. En fait, les variables globales sont utilisées comme point de départ. En effet, dans l'exemple, pour calculer un factoriel, il faut partir de 1, puis executer la boucle jusqu'à n. A l'aide des globales, on peut maintenant partir du de la dernière valeure calculée, c'est à dire de la valeure calculée depuis la dernière fois où la fonction a été appellée ... Pas clair ?
On va utiliser une première fois la fonction pour calculer le factoriel de 5.
La fonction va faire une boucle, de 1 à 5.
Après le calcul, le tableau global va changer, et contenir '5' comme input et '120' dans 'output' (le factoriel de 5 vaut 120). Imaginons ensuite que le script doit ensuite calculer le factoriel de 7. Et bien, grâce au tableau, il n'aura pas à partir de 1, mais de 5 ! D'où un gain de temps et une optimisation non négligeable ! Voilà, j'espère que c'est un peu plus clair ...
Pour prouver ce que j'avance, des petits tests. J'ai calculé le factoriel de 12 nombre à la suite, avec chacune des fonctions. Et voilà le resultat :
factoriel_1 : 6.853ms
factoriel_2 : 9.211ms
factoriel_3 : 5.152ms
Convaincu ?
Il est bien entendu interessant d'utiliser ces variables spéciales uniquement si une fonction est souvent appellée, sinon ... Bon ... On peut s'en passer.
@ la prochaine !
++ !
LocalStone.


 Historique

16 octobre 2004 14:45:56 :
Je me suis trompé dans les chiffres, alors c'était plus très très crédible ... :)
17 octobre 2004 17:06:23 :
2 ou 3 petites corrections ... Merci Kirua !

 Sources du même auteur

Source avec Zip Source avec une capture MOTEUR D'ASPECT POUR PHP
Source avec Zip [PHPHOOK] UN PETIT SYSTÈME DE GESTION DES HOOKS DE SUBVERSIO...
Source avec Zip [PHP5] TASKSCHEDULER, UN PETIT PLANIFICATEUR DE TÂCHE EN PHP...
Source avec Zip [PHP5] NAVIGUER DANS UNE COLLECTION À L'AIDE D'UNE PSEUDO SY...
Source avec Zip Source avec une capture CLASSE D'ÉDITION DES FICHIERS DE CONFIGURATION D'APACHE

 Sources de la même categorie

AFFICHÉ SUR UN TABLEAU AVEC PAGINATION ET BASE DE DONNÉES par stormxp
Source avec Zip Source avec une capture GENERATEUR D'ONGLET DE NAVIGATION PHP par pos123
FORMATER UN LIEN YOUTUBE, DAILYMOTION OU VIMEO POUR L'UTILIS... par kgb93
Source avec Zip Source avec une capture PAGINATION + FICHIER CSS par profdi
Source avec Zip Source avec une capture SYSTEME D'AUTHENTIFICATION PHP AVEC PROTÉCTION KEYLOGGER par mtrix000

Commentaires et avis

Commentaire de windu le 16/10/2004 17:02:58

pas mal du tout ce tutoriel... par contre juste une peitie correction dans la 1° fonction tu marque "return($n * factoriel($n - 1));", or il faut écrire "return($n * factoriel_1($n - 1));" puisque c'est une fonction récursive!
Erreur qui ne te vaudra que 9/10... loooool

Commentaire de juki_webmaster le 16/10/2004 17:12:07

Ahh dommage, il à louper son 10/10 :( lol
Belle source!
Bonne continuation.

Commentaire de LocalStone le 17/10/2004 01:28:32

Merdeuuuuuuuh, j'avais pas vu quand j'ai changé le nom des fonctions ... Snif. En tout cas, je suis content que ça ait plu à quelqu'un ...
Merci !
L.S.

Commentaire de Kirua le 17/10/2004 14:16:54

l'itérative sera certainement plus rapide que la récursive. il faut pas appeler l'itérative la fonction barbare, elle est meilleure ;)

dans ta description, tu dis que factoriel de n = n! = 1*2*3*...*(n-1)*(n+1), c'est *(n) et pas *(n+1), bien sûr, mais tu le sais. faut juste corriger la coquille.

ta troisième fonction est-ce qu'on appelle un algorithme dynamique, càd qu'à mesure qu'on l'utilise, il accélère parce qu'il sauve les résultats intermédiaires. on utilise exactement le même procédé pour les suites de fibonacci, quoique pour fibo justement, l'itérative va aussi vite que la dynamique, et environ une infinité de fois plus vite que la récursive ;)

comme ton tableau n'est utilisé que dans la fonction dynamique, tu peux déclarer ce tableau en static plutôt, et donc le tuto n'a plus rien à voir avec les globales :p ça ne change rien à l'intérêt du pt que tu soulèves, mais static sera plus approprié. cf http://be2.php.net/variables.scope

j'ai pas assez lu ton code pr savoir mais... il me semble que tu ne sauves qu'un seul résultat (et en plus ds un tableau à indices littéraux, ce qui est bcp plus lent que les indices numériques, mais soit). docn si je fais ça:

50!

et puis

49!

si j'ai bien compris, il recalcul tout, ou pas?

je reconnais que c'est une perte de place mais... souvent on sauvera toutes les factorielles calculées dans un tableau, et on combinera avec une récursive. je m'explique:

function facto($n)
{
        //ce tableau n'existe que dans cette fonction
static $tab = array();

//si l'élément a déjà été calculé
if(isset($tab[$n]))
{
return $tab[$n];
}
//sinon
else
{
$res = facto($n-1) * $n;
$tab[$n] = $res;
return $res;
}
}


du moins c'est comme ça que je ferais. comme les factorielles montent TRES vite, tu n'auras jamais 1000 éléments dans ton tableau (en fait même BCP BCP moins), et donc tu ne perds pas tant de place que ça.

faudrait tester la vitesse de cette fonction-ci. en tt cas le code est minuscule et facile.

ciao ! bonne continuation.

Commentaire de Kirua le 17/10/2004 15:03:35

note: il faut remplacer

static $tab = array();

par

static $tab = array(1);

Commentaire de LocalStone le 17/10/2004 17:03:51

Oh ! Kirua, ça faisait longtemps !
C'est dommage que les fonctions récusives soient lentes, parce que je trouve ça super pratique est simple à coder ... Mais bonjour les overflows sur le serveur.
Alors déjà, pour répondre à ta question, si tu fais 50! et 49!, la fonction va détécter que ça vaut le coup de décrementer le factoriel d'une unité (je sais pas si ça se dit, donc : (50 - 1)! = 49!), donc il va diviser le factoriel de 50 par 50, pour arriver au factoriel de 49.
Ensuite, pour les variables statiques, bah je sais pas ce que c'est donc je vais aller voir de ce pas le lien. Merci d'avance. Par contre, je sais que les (string) au lieu des (int) comme clef d'un tableau, ça ralenti, mais je vais laisser comme ça, pour ... Disons la pédagogie. Mais tu as raison.
Enfin, oui, le script ne sauve que la dernière valeure. Et tu as raison, comme les factoriels monte rapidement, ta solution est bonne. Mais en fait j'ai appris cette technique des variables globales (ou statiques) avec le coefficient binomial (P parmis N ...), mais comme tout le monde ne connait pas forcement ça, mais plutôt le factoriel, bah voilà ...
Mais je vais de ce pas voir les variables statiques ...
Merci de ton commentaire, Kirua !
++ !

Commentaire de LocalStone le 17/10/2004 17:25:32

Bon, donc j'ai regardé les variables statiques, et en fait, ça ne sert plus à rien mon tutorial, puisqu'elles font exactement ce que font mes globales ... Snif.
Bon, bah je vais pleurer et je reviens :(
++ !

Commentaire de Kirua le 17/10/2004 18:25:05

suis bien d'accord avec toi, les fonctiosn récursives c'est beau à mourir :) mais si c'st lent... ben faut laisser tomber.

remarque que parfois, la récursivité reste tt de même reine, je pense aux parcours d'arbre binaires par exemple, sans la récursivité, je sais pas comment on fait, lol.

Commentaire de Kirua le 17/10/2004 18:35:55

dis ... je suis un peu gêné ... je viens de regarder les commentaires de tous tes codes pour voir où on aurait pu se croiser auparavant, parce que je me souviens pas de toi, ... dsl :D et j'ai pas trouvé où. tu me rafraîchis la mémoire? j'ai aussi regardé sur ts mes codes php, et rien ...

Commentaire de LocalStone le 17/10/2004 23:53:12

Y a pas de mal, Kirua. En fait, je disais que ça faisait longtemps, parce que ça faisait longtemps que je n'avais pas lu un des tes commentaires, voilà tout.
++ !

Commentaire de Kirua le 18/10/2004 00:02:12

oki, content d'être lu :p

je vais me coucher à l'instant, bye bye ;)

Commentaire de mehdibou le 18/10/2004 16:41:52

He oui, Kirua, je te lis aussi, tu es une star ;)
(à quand une équipe de Belgique pour les IOI ?)

Et pour parcourir un arbre binaire sans fonction récursive, on peut se faire sa propre pile (en gros ça revient à faire un appel) pour une moitié et utiliser un while pour l'autre moitié, c'est assez barbare :)

Comme l'a dit Kirua, il vaut mieux utiliser un tableau complet indicé pour la fonction factorielle mais la méthode que tu montres (ne garder qu'une valeur) peut être intéressant si on est très limité en place et si les valeurs demandées sont assez proches (sinon ça revient quasiment à tout calculer et en pratique ça prendra même plus de temps), comme par exemple une courbe continue.

Commentaire de Kirua le 18/10/2004 17:43:11

les IOI ça me fait bien râler. En france ils ont un truc génial qui s'appelle ProLogin, qui est un organisme de préparation et de sélection des ados qui iront défendre la France pour les concours d'algorithmique. En Belgique, rien de tout ça :(

Je vois ce que tu veux dire pour la pile/file, c'est vrai qu'on peut le faire comme ça, et c'est en fait ce qu'on utilise pour des problèmes comme les N reines etc. J'y avais pas pensé, mais en fait on parcours bien un arbre virtuel, c'est bien vu ^^

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,608 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales