PROGRAMMATION ET ENSEIGNEMENT
Contenu du cours 7 Procédures et fonctions Introduction Syntaxe Appel des procédures et fonctions Passage de paramètres Autres exemples de procédures et fonctions: Calcul de PI Récursivité Algorithme récursif Exemples d’implémentation Notes de cours (site ftp UQTR)
Introduction En programmation il est déconseillé d'écrire l'ensemble d’un programme dans un seul bloc. De tels programmes sont beaucoup plus difficile à déboguer. De plus, de tels programmes sont beaucoup plus difficile à entretenir, à modifier. Les notions de procédure et de fonction permettent de découper un programme en plusieurs sous-programmes. Ainsi, le débogage de tels programmes devient plus facile car il ne suffit que de tester chaque sous-programme (procédure/fonction). L’ajout de fonctionnalités à un programme est aussi grandement facilité.
Syntaxe En VB.NET les procédures sont identifiée par le mot réservé Sub et les fonctions par le mot réservé Function. La différence fondamentale réside dans le fait qu'une procédure ne retourne pas de valeur alors qu'une fonction en retourne.
Syntaxe: Exemple 1 Sub affichage (ByVal V as single) Console.writeline (V) End Sub Paramètre(s) passé(s) Nom de la fonction
Syntaxe: Exemple 2 Function Carre (ByVal V as Single) as Single Return V*V End Function Cette fonction se nomme 'Carre'. Elle reçoit un paramètre de type single et retourne le carré du paramètre V reçu en entrée et ce en utilisant l’énoncé Return. Type de la valeur retournée
Appel des procédures et fonctions: Exemple 3 ‘Pour utiliser une procedure/fonction: appel Dim resultat As Single resultat = carre(2) Affichage (resultat) On appelle la fonction carre avec le paramètre 2, elle retourne 4 qui sera affiché par la procédure Affichage(). Les paramètres peuvent être des variables: Dim resultat As Single Dim valeur As Single=3 resultat = carre(valeur)
Appel des procédures et fonctions: Remarques Remarque 1 : même s'il n'y a pas de paramètre, mettre des () lors de l'appel de procédure. MaRoutine() Remarque 2 : la fonction peut ne pas utiliser le mot réservé return. Dans ce cas, la variable de retour sera associée au nom de la fonction est utilisée. Function Carre (ByVal V as Single) as Single Carre = V*V End Function
Passage de paramètres Il y a deux façons de passer des paramètres aux procédures et fonctions : Par valeur (ByVal). C’est la valeur de la variable qui est passée en paramètre. Si la variable est modifiée dans le sous-programme (procédure/fonction), cette modification ne sera pas visible dans la procédure (fonction) appelante. Par référence (ByRef). C’est une adresse qui est passée en paramètre. Si le sous-programme (procédure/fonction) modifie le contenu de la variable, cette modification sera alors visible dans la procédure (fonction) appelante.
Passage de paramètres: Exemple 1 Sub MaProcedure (ByRef x as Long, ByVal y As Long) … End Sub Si cette procédure est appelée à partir de la procédure principale main() d’une application console : Sub Main() MaProcedure (A, B) Console.writeline (A) Console.writeline (B) End Sub L'adresse de A est passée comme premier paramètre et la valeur contenue dans la variable B comme deuxième paramètre. Elles sont copiées dans les variables x et y de la procédure MaProcedure(). Les variables x et y sont dites locales à la procédure MaProcedure(). Si dans cette procédure nous modifions x, A est aussi modifié dans la Sub Main() (puisque x et A pointe (réfère à) sur la même adresse). Si dans MaProcedure() y est modifié, B n’est pas modifié dans la procédure principale (main()).
Passage de paramètres: Exemple 2 Sub MaProcedure (ByVal Variable As Integer) Variable=Variable+4 End Sub Sub main() Dim A As Integer = 3 MaProcedure(A) Console.writeline (A) Après l'appel de la procédure MaProcedure() avec A=3, Console.writeline (A) affiche '3'
Passage de paramètres: Exemple 3 Sub MaProcedure (ByRef Variable As Integer) Variable=Variable+4 End Sub Sub Main() Dim A As Integer = 3 MaProcedure(A) Console.writeline (A) Après l'appel de la procédure MaProcedure() avec A=3, Console.writeline (A) affiche '7'
Passage de paramètres: Remarques Remarque 1 : Si on n'indique pas ByVal ou ByRef, par défaut les paramètres sont passés par valeur. Toutefois pour la clarté du code et pour éviter toute ambiguïté toujours spécifier ByRef ou ByVal. Exemple d'ambiguïté : Écrire : Sub MaProcedure (ByRef x as Long, ByVal y As Long) Au lieu de : Sub MaProcedure (x as Long, y As Long)
Passage de paramètres: Remarques Remarque 2 : Un paramètre peut être facultatif. « Optional » indique que cet argument n'est pas requis lorsque la procédure est appelée. Chaque déclaration de paramètre facultatif doit indiquer une valeur par défaut qui sera utilisée dans la routine s'il n'y a pas de paramètre. Les paramètres par défaut sont utilisés principalement quand leur contenu change très peu. Sub MaRoutine (ByVal X as integer, Optional ByVal Y As Integer=0) … End sub Sub main() Maroutine (3, 4) Maroutine (3) End Sub
Passage de paramètres: Tableaux Il est possible de passer un tableau comme paramètre. Sub Affiche (ByVal tab() As Integer) … End Sub Sub main() Dim Reponses(10) As Integer Affiche(Reponses()) End sub
Passage de paramètres: Tableaux Remarque 1 : Parfois il faut envoyer des paramètres de même type mais dont on ne connaît pas le nombre, dans ce cas on utilise ParamAray (Liste de paramètres): Function Somme (ByVal ParamArray Valeurs() as Integer) As Integer Dim i as Integer Dim Total as Integer = 0 For i = 0 to Valeurs.Length-1 Total += Valeurs(i) Next i Return Total End Sub Dim LeTotal As Integer LeTotal = Somme (2, 5, 6, 8 ,5) Remarque 2 : le paramètre ParamArray doit être le dernier des paramètres, c'est obligatoirement un paramètre ByVal, tous les paramètres sont de même type.
Autres exemples de procédures et fonctions: Calcul de PI (Voir VBNET-EX14-PI) Formule de Gregory et Leibniz (convergence lente)
Autres exemples de procédures et fonctions: Calcul de PI Formule de Nilakantha (convergence plus rapide)
Autres exemples de procédures et fonctions: Calcul de PI Méthode de Monte Carlo +1 A cercle/A carre = /4 Une expérience de Monte Carlo consiste à générer un certains nombres de coordonnées aléatoires dans l’intervalle -1, 1 en x et en y et ensuite calculer le rapport : Hits sur le cercle/Nb Essais Sachant que: Hits sur le cercle/Nb Essais = /4 Alors = 4 X (Hits sur le cercle/Nb Essais) +1 -1 +1 -1
Récursivité En mathématiques et en informatique, la récursivité signifie faire référence à soi même. La récursivité est une technique de programmation qui consiste à ce qu’une méthode s’appelle elle‐même (directement ou indirectement). Bien que le concept puisse paraître étrange, la récursivité permet bien souvent de trouver des solutions très compactes et très élégantes à des problèmes complexes qui, autrement, pourrait être difficilement résolubles en utilisant des algorithmes «standards» utilisant des boucles(des méthodes itératives). La récursivité est un concept important qu’il faut apprendre à bien utiliser.
Récursivité Le concept est très proche du principe de raisonnement par récurrence en mathématique: Raisonnement par récurrence: démontrer une propriété portant sur tous les entiers naturels en se basant sur le fait que si une propriété est satisfaite par un entier initial (P(0)) et qu’elle est satisfaite par un nombre entier n quelconque, alors elle doit être aussi satisfaite par n + 1 (P(n) => P(n+1)), et donc pour l’ensemble des nombres entiers naturels. Toute fonction définie par récurrence peut être traduite de façon récursive (séries/suites numériques, etc.).
Récursivité Une procédure ou une fonction peut s'appeler elle-même, et dans ce cas on va parler d'une procédure ou d'une fonction récursive. VB accepte les procédures récursives: Sub Procedure() … Procedure() ... End Sub L'appel récursif de la procédure Procedure() se fait avec de nouveaux paramètres. Les variables locales à la procédure auront une portée (visibilité) limitée à cette procédure lors de l'appel. Une procédure non récursive appelle, elle, d'autres procédures. Une procédure récursive découpe le problème en morceaux plus petit et s'appelle elle même pour résoudre chacun des plus petits morceaux, elle résout une petite partie du problème elle même.
Récursivité En opposition avec une méthode itérative; c’est une méthode qui s’appelle elle‐même 1 à nfois de façon à résoudre un sous‐problème plus simple. Appel récursif : appel à même la méthode.
Division du problème en deux parties: Algorithme récursif Division du problème en deux parties: Le ou les cas de base(ou cas élémentaire(s)): Cas pour lequel la solution est connue: Renvoie un résultat sans appel récursif; Condition d’arrêt de la récursivité (ou d’une branche de récursivité s’il y a plus qu’un appel récursif possible à l’intérieur de la méthode): nécessaire pour assurer que le problème puisse être résolu et que la récursivité cesse. Le cas complexe: Cas pour laquelle la solution est fonction d’une autre solution dans un cas plus simple: Le résultat retourné dépend du résultat retourné par l’appel récursif; La méthode récursive appelée est un cas plus simple qui se rapproche davantage d’un cas de base.
Algorithme récursif Sub Procedure(ensemble input) … End Sub If (test d'arret) Résolution d'un problème simple sans appel de la procédure Procedure(…) Else … Procedure(ensemble input réduit) End If End Sub
Algorithme récursif Sub Procedure(ensemble input) If (test qui permet l'appel récursif) … Procedure(ensemble input réduit) End If End Sub A un moment donné, la condition n'est pas remplie, cela correspond à l'arrêt de l'appel récursif. Remarque : On se rend compte qu'une boucle For Next peut être transformée en procédure récursive
For Next à récursif: Exemple Function fonction(ByVal N As Integer) as integer Dim i as integer Dim total as integer = 0 For i = N to 1 Step-1 total = total + i Next i Return total End function Function fonction(ByVal n As integer) as integer If (n = 0) return 0 Else return n + function (n-1) End If End function Dans les deux cas l'appel peut se faire par: Dim toto = fonction(20) Remarque : l'exemple donné est relativement simple. Toutefois dans la réalité de la programmation certains problèmes ne trouvent une solution pratique qu'en adoptant la programmation récursive.
Algorithme récursif: Exemple n! La fonction factorielle (n!) consiste à multiplier la valeur de n termes entre eux et est définie comme suit: Si n = 0, alors n! = 1; Si n > 0, alors n! = n (n –1)!; Ainsi: 0! = 1; 1! = 1; 2! = 2 x (2‐1)! = 2 x 1! = 2 x 1 = 2; 5! = 5 x (5‐1)! = 5 x 4! = 5 x 4 x (4‐1) != 5 x 4 x 3! = … = 5 x 4 x 3 x 2 x1 = 120; ….. n! = n x (n‐1) x (n‐2) x … x 1; Donc, si n = 0 alors la solution est de 1. Cela constitue le cas de base. Dans les autres cas, nous sommes dans un cas complexe qui nécessite une récurrence.
Calcul de la fonction factorielle (Voir VBNET-EX15-Factorielle) Factorielle itérative : Function Factorielle (ByVal N as Long) As Long Dim i As Long Dim Resultat As Long Resultat = 1 For i = 1 to N Resultat = i * Resultat Next i Return Resultat End Function Factorielle récursive : Function Factorielle (ByVal N as Long) As Long If N = 1 then Return 1 Else Return N * Factorielle(N-1) End If End Function Remarque : pour gérer les appels récursifs VB utilise une pile. La pile a une taille maximum, si N est trop grand, on déclenche une erreur de type StackOverflow.
Plus Grand Commun Diviseur (Voir VBNET-EX16-PGCD) Function PGCD(ByVal a As Long, ByVal b As Long) As Long Dim resultat As Long If(a = b) then resultat = a Else If (a > b) then resultat = PGCD(a - b, b) Else resultat = PGCD(a, b - a) End If Return resultat End Function
Plus Grand Commun Diviseur ( Autre Version) Sub Main() Dim m, n, g As Integer Console.Write("Entrer le premier nombre : ") m = CInt(Console.ReadLine()) Console.Write("Entrer le second nombre : ") n = CInt(Console.ReadLine()) g = gcd(m, n) Console.WriteLine("PGCD = " + g.ToString()) Console.ReadLine() End Sub Function gcd(ByVal x As Integer, ByVal y As Integer) As Integer If x Mod y = 0 Then Return y Else Return gcd(y, x Mod y) End If End Function
Nombres triangulaires (Voir VBNET-EX17-NOMBRE-TRIANGULAIRE) Considérons la série numérique suivante: 1, 3, 6, 10, 15, 21, … …où le n ième terme de la série est obtenu en ajoutant n au terme précédent: 1 er terme: 1; 2 ième terme: 1 + 2 = 3; 3 ième terme: 3 + 3 = 6; 4 ième terme: 6 + 4 = 10; 5 ième terme: 10 + 5 = 15; … N ième terme: f(n‐1) + n.
Nombres triangulaires Cette série est appelée celle des nombres triangulaires, de par l’arrangement triangulaire possible du nombre d’éléments en fonction de n(équivalent au nombre de colonnes/rangées).
Nombres triangulaires (version itérative) Sub Main() Dim i, j, n As Integer Console.Write("Entrer le nombre de lignes (Etages): ") n = CInt(Console.ReadLine()) For i = 1 To n For j = 1 To i Console.Write("" & " ") Next Console.WriteLine() Console.ReadLine() End Sub
Nombres triangulaires (version récursive) Sub Main() Dim i, j, n As Integer Console.Write("Entrer le nombre de lignes (Etages): ") n = CInt(Console.ReadLine()) SurfaceTriangle(n) Console.ReadLine() End Sub Function SurfaceTriangle(ByVal LargeurBase As Integer) As Integer Dim Surface As integer If LargeurBase < = 0 Then Return 0 End If If LargeurBase = 1 Then Return 1 Surface = LargeurBase + SurfaceTriangle(LargeurBase - 1 ) Return Surface End Function
Nombres de Fibonacci (Ex: Calcul du nombre de paires de Lapins)
Nombres de Fibonacci (Voir VBNET-EX18-FIBONACCI) Sachant que la séquence de nombres de Fibonacci est définie par: f0 = f1 = 1 fn = fn-1 + fn-2 À partir de cette expression, nous pouvons alors déduire chaque valeur de la séquence en additionnant les deux derniers termes de cette séquence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ….
Nombres de Fibonacci Exemple d’arbre d’appels (récursif) de f(4) :
Nombres de Fibonacci Cette séquence de nombres de Fibonacci peut aussi être déduite par la sommation des éléments des diagonales sous-jacentes du triangle de Pascal (voir la création du triangle: https://en.wikipedia.org/wiki/Pascal%27s_triangle
Nombres de Fibonacci (version itérative) Sub Main Dim a As Integer = 0 Dim b As Integer = 1 Dim fib As Integer = 0 Do fib = a + b a = b b = fib Console.WriteLine(fib & ControlChars.NewLine) Loop While fib < 55 End Sub
Nombres de Fibonacci (version récursive) Sub Main Dim number As Integer = 13 Console.WriteLine(" La valeur de Fibonacci est " & Fibonacci(number)) End Sub ' calcul du nombre de Fibonacci (recursif) Function Fibonacci(ByVal number As Integer) As Long ' Verification du cas de base If number = 1 OrElse number = 0 Then Return number Else Return Fibonacci(number - 1) + Fibonacci(number – 2) End If End Function ' Fibonacci
Itération et récursivité Impliquent toutes les deux une répétition; Itération: utilisation d’une structure de contrôle de boucle; Récursivité: appels de méthodes récursives. Condition d’arrêt nécessaire pour les deux approches afin que l’algorithme puisse se terminer dans un temps fini; Approche progressive dans les deux cas (dû à la nature répétitive des algorithmes)