UNIVERSITE PARIS 7 DENIS DIDEROT UFR DE MATHEMATIQUES PREPARATION CAPES 2003-2004 CALCULATRICES (III) De nombreux calculs sur les calculatrices actuelles, en particulier les calculatrices formelles, ne nécessitent pas de programmation. Les langages de programmation dépendant des calculatrices, on s'intéressera d'abord aux algorithmes et à leurs structures avant d’aborder la programmation. On a choisi cependant l’expression des algorithmes dans un langage le plus proche possible des langages utilisés dans les calculatrices pour faciliter les traductions nécessaires. D’autre part, ayant en vue l’oral du CAPES, on n’a pas cherché la sophistication mais l’efficacité et l’économie. I. STRUCTURES ALGORITHMIQUES ET PROGRAMMATION Considérons l’exemple suivant : écrire un programme qui calcule la somme des carrés des n premiers entiers1. Les deux algorithmes suivants peuvent servir de base à un tel programme : Algorithme 1 : Entrée : N (entier positif) Initialisation : S := 0 Pour K allant de 1 à N, pas de 1 S ← S+K2 Finpour Rendre S Sortie : Somme Algorithme 2 : Entrée : N (entier positif) Initialisation : S := 0 Tantque N>0 S ← S+N2 N ← N−1 Fintantque Rendre S Sortie : Somme On retrouve dans ces deux algorithmes des étapes (entrée, initialisation, boucle, sortie) qui vont se traduire de la façon suivante au niveau de la programmation : Entrée de données C’est ce qui correspond aux entrées de l’algorithme. Cela se traduit par une instruction de programmation qui suspend l’exécution jusqu'à la frappe de valeurs pour les entrées par l'utilisateur. Ici il y a une seule entrée, l’entier N. Sa valeur est affectée à la variable N. Initialisation des variables : Un algorithme fait en général intervenir plusieurs variables. Ici les variables N et S (algorithme 2), les variables N, S et K (algorithme 1). Certaines doivent être initialisées. C’est le cas ici de la variable S à laquelle on affecte la valeur 0. L’écriture standard pour une telle affectation est S := 0 (ou S ← 0). Affichage de données : C’est ce qui correspond aux sorties de l’algorithme. Ceci se traduit par une instruction d’affichage. A l'écran, pour les deux algorithmes, on fait ici afficher la valeur de S. On peut aussi faire afficher d'autres types d'objets, notamment des chaînes de caractères. Structure d'itération ou boucle : Elle est ici présentée sous deux formes : • Pour <variable, valeur initiale, valeur finale, incrément> : <Instructions> : FinPour (algorithme 1) • Tantque <condition> : <Instructions> : Fintantque (algorithme 2). 1 Avec une calculatrice symbolique, il n’est bien sûr pas nécessaire d’écrire un programme pour calculer une telle somme k, 0, N) ) ( Σ(k2, 1 La première forme suppose que le nombre de boucles soit connu à l’avance, ce qui est le cas ici. On ne trouve pas en revanche dans ces deux algorithmes très simples une structure fondamentale qui est la structure conditionnelle : Structure conditionnelle : Si <condition> alors : <Instructions> : sinon : <Instructions> : FinSi II. ADAPTATION AUX CALCULATRICES Cette adaptation va dépendre des modèles de calculatrices. Les modèles récents se rapprochant de plus en plus des écritures algorithmiques codifiées ci−dessus. Entrée de données : Elle se fait via Input et Prompt sur les modèles Texas, via ?→ sur Casio. Il est utile de faire afficher sur l'écran à quelle variable correspond la donnée demandée : Prompt le fait automatiquement (ex : prompt N se traduit par l’affichage ?N). Sinon faire : Input "N=", N (Texas), "N="?→N (Casio) Initialisation des variables : Se fait avec STO pour les Texas et avec la flèche → pour les Casio Affichage de données : Se fait avec Disp sur Texas. Sur Casio, après le nom de la variable, taper la touche triangle noir Structures d'itération : La structure Pour <variable, valeur initiale, valeur finale, incrément> : <Instructions> : FinPour se traduit par : For variable (valeur initiale, valeur finale, incrément) <Instructions> EndFor avec des petites variantes suivant les modèles. L'incrément est facultatif s'il est de 1. Par exemple, sur Casio 99** : For <valeur initiale>→<nom de la variable> to <valeur finale> Step <valeur du pas> <Instructions> Next avec là encore, Step facultatif si le pas est de 1. Pour ce qui est des boucles intégrant une condition, les machines anciennes avaient seulement une structure de saut inconditionnel de la forme : Label <numéro> <Instructions> Goto <numéro> La structure Tantque <Condition> : <Instructions> : Fintantque se programmait alors de la façon suivante : Label 1 Si non <Condition> Goto 1 Label 2 Pour les machines récentes, la structure : While <Condition> <Instructions> EndWhile (ou ses variantes suivant les modèles) est la structure fondamentale et elle traduit directement l'algorithme. Mais les machines proposent aussi d'autres structures. 2 Sur TI : Repeat Condition <Instructions> End Cette forme permet la répétition d’un groupe d'instructions jusqu'à ce que la condition soit vraie, mais la condition est examinée quand <instructions> a été exécuté, ce qui fait que le groupe d'instructions qui suit Repeat est exécuté au moins une fois. Sur Casio 99** : Do <Instructions> LpWhile Condition Les instructions suivant Do sont répétées tant que la condition est vraie comme pour While… EndWhile. Mais comme la condition est en fin, elle est testée après exécution du bloc d'instructions intérieur à la boucle. Sur TI, on a aussi une boucle simple : Loop < Instructions> EndLoop dont on peut sortir avec un instruction Exit via la syntaxe : Loop <Instructions> If Condition Exit EndLoop Par exemple : : Loop : Prompt a,b : If f(a)*f(b)>0 : Exit : EndLoop, Sur Casio, la commande Break à l'intérieur d'une boucle interrompt l'exécution de la boucle et fait sauter à l'instruction suivant la fin de la boucle. Conditionnelles : Les calculatrices les plus simples avaient seulement un saut conditionnel du type : If <Condition> <Instruction 1> <Instruction 2> ou (Casio) : <Condition>⇒<Instruction 1> <Instruction 2> Instruction 1 est exécutée si Condition est vraie et instruction 2 sinon. l'instruction 1 n'étant effectuée que si la condition est satisfaite. Les machines actuelles ont des structures de programmation qui correspondent exactement à la structure : Si <Condition> alors <Instructions> sinon <Instructions> FinSi, sous la forme : If <Condition> Then <Instructions> Else <Instructions> EndIf ou des formes très voisines, et elles permettent de plus l'imbrication des ces structures. Par exemple, les TI89 et 92 comportent des structures : If <Condition 1> Then <Instructions 1> Elseif <Condition 2> Then 3 <Instructions 2> Esle <Instructions 3> EndIf Les conditions peuvent être des combinaisons logiques de conditons. Remarques : 1. Il est prudent de déclarer comme locales les variables internes à un programme car ces variables peuvent avoir déjà dans la machine une affectation. 2. Vous pouvez aussi définir des fonctions par programmation. Par exemple, pour la somme des carrées des n premiers entiers, cela donnera sur les TI89 et 92 : : : : : : : : : : : : : : sommeca(n) Func Local s If n≥0 Then 0→ s While n≥0 s+n^2→ s n−1 → n EndWhile Return s Else "n doit etre positif" End Dans l'application HOME, vous demandez les valeurs de la fonction de façon usuelle, en tapant : sommeca(10) par exemple pour avoir la somme des carrés des dix premiers entiers. La frappe de sommeca(−1) renverra : undef. 4 III. QUELQUES EXEMPLES D’ALGORITHMES EN ANALYSE 1. Programmes sur les suites : Rappelons qu’il n'est pas nécessaire avec les machines graphiques actuelles de programmer pour obtenir des valeurs d'une suite. Des programmes peuvent cependant être utiles lorsque des calculs doivent être itérés, tant qu'une condition est satisfaite, et que l'on ne sait donc pas exactement les termes que l'on veut calculer. Exemple 1 : La suite est définie par une récurrence de la forme un+1 = f(un). Elle converge et les termes de la suite sont tels que deux termes consécutifs soient situés de part et d'autre de la limite. Alors, pour approcher avec une précision ε donnée, il suffit de calculer un jusqu'à ce que un − un−1 soit en valeur absolue inférieur à ε. Bien sûr, la même condition ne garantit absolument pas que c'est le cas, si l'on sait simplement que la suite est convergente. Entrées : la valeur initiale U0 et la précision P (correspondant à ε = 10−p) Variables locales : X, Y, I Initialisation : X := U0 ; N := 0 Y ← f(X) I ← ABS(Y − X) Tanque I>10^-p X←Y Y ← f(X) I ← ABS(Y− X) N←N+1 FinTantque Rendre N, X, Y Sortie : N, uN et vN Remarque : la fonction f peut être systématiquement stockée dans Y1 de Y= ou définie dans HOME (si l’on souhaite travailler en calcul exact) , ce qui n'oblige pas à modifier le programme quand on change de fonction. Cet algorithme s'adapte sans difficulté à des suites du type un+1 = f(n,un) Exemple 2 : Adapter cet algorithme à l'étude de deux suites adjacentes imbriquées : un+1=f(un, vn) vn+1=g(un, vn) Entrées : valeurs initiales U0, V0 et précision P Initialisation : X := U0 ; Y := V0 ; I := ABS(Y−X) ; N := 0 Tanque I>10^-P Z ← F(X,Y) Y ← G(X,Y) X←Z N ← N+1 I ← ABS(Y−X) FinTanque Rendre N, X, Y ère Voir CAPES 1995 1 épreuve : a+b a0=a, b0=b, an+1= n n et bn+1= anbn 2 Démontrer que ces suites sont convergentes et qu'elles ont la même limite. Les programmer. Sortie : N, uN et vN tels que uN−vN ≤10-p 5 2. Résolution d’équations : Exemple 1 : Méthode par dichotomie On considère une fonction f continue sur l’intervalle [a;b] avec a<b et telle que f (a) × f (b) < 0. Le théorème des valeurs intermédiaires nous assure alors que f s’annule au moins une fois dans cet intervalle. Pour obtenir une solution de l’équation f (x)=0, la méthode par dichotomie procède de la façon a+b ; si cette valeur est nulle, on a trouvé une solution et suivante : on calcule la valeur de f pour 2 a+b l’algorithme s’arrête ; sinon, suivant le signe de f (a) × f , on réduit l’intervalle de recherche d’une 2 a+b a+b solution à [a; ] ou à [ ;b]. On itère le processus jusqu’à obtenir soit une solution, soit un intervalle 2 2 de largeur inférieure à ε, ε étant une précision donnée à l’avance. Algorithme : Entrées : A, B (A<B) et la précision P Initialisations : X := A, Y := B, I := Y−X Tantque I>10^-p et f((X+Y)/2) ≠ 0 Si f(X)*f((X+Y)/2) < 0 Alors Y ← (X+Y)/2 Sinon S ← (X+Y)/2 FinSi I ← Y−X Fin Tantque Si F((X+Y)/2)=0 Alors rendre "solution =" et (X+Y)/2 Sinon rendre "encadrement", X et Y FinSi Sortie : un nombre x qui vérifie f(x)=0 ou un encadrement à 10-p Autres méthodes : Méthode de la sécante, ou de la corde, ou de Lagrange. Méthode de Newton 3. Calcul d'intégrales On suppose f définie et intégrable sur [a;b]. On va présenter trois algorithmes associés aux trois méthodes classiques : méthode des rectangles, méthodes des trapèzes, méthode de Simpson. Comme pour les sommes partielles de série, l'écriture pour des calculatrices formelles ne nécessite pas de programmation. 1. Méthode des rectangles On prend comme hauteur du rectangle sur chaque subdivision de l'intervalle la valeur de la fonction au point médian. Si n est le nombre de subdivisions, la valeur approchée est : k=n A1(n) = b−a n ∑ b−a f a + 2k−1 2n ( ) k=1 (b−a) sup f ' sur [a;b], on rappelle que l’erreur commise est alors majorée par : 3 Si f est C 1 2n L’algorithme associé est le suivant : Entrées : valeurs des bornes de l’intervalle A et B et du nombre de subdivisions N Initialisation : S := 0 6 Pour K allant de 1 à N par pas de 1 B−A S := S+f A+(2K−1) 2N FinPour B−A Rendre S* N Sortie : approximation de l'intégrale Remarque : On a utilisé ici la méthode des rectangles avec le point médian de l’intervalle. On peut aussi l’utiliser en prenant l’extrémité gauche de l’intervalle ou l’extrémité droite. Lorsque la fonction est monotone sur [a;b], on obtient ainsi deux suites (un) et (vn) adjacentes qui convergent vers l’intégrale cherchée. Pour avoir une valeur approchée de l’intégrale à ε près, il suffit alors de choisir n tel que la valeur absolue de un – vn est inférieure à ε. 2. Méthode des trapèzes : On approche l'aide sur chaque subdivision [xk ; xk+1] par celle du trapèze de sommets (xk ; 0), (xk ; f(xk)), (xk+1 ; f(xk+1)), (xk+1 ; 0) soit par : b−a [f(xk) + f(xk+1)] 2n On obtient alors pour l’aire totale l’expression : k=n−1 b−a b−a A2(n)= f(a) + f(b) + 2 f a + k 2n n k=1 ∑ Si f est C2, une majoration de l'erreur est, dans ce cas, fournie par l’expression : (b−a)3 supf" 12n2 Variante : On calcule l'aire du trapèze dont le côté supérieur est la tangente en xk+xk+1 ; ou (ce qui revient au même) 2 x +x le rectangle de base [xk ; xk+1] et de hauteur f k k+1. 2 Avec les mêmes hypothèses on trouve une erreur majorée par : (b−a) 3 24n2 () supf" 3. Méthode de Simpson : On approche la courbe sur chaque subdivision par un arc de parabole qui passe par les extrémités et le point médian. Exercice : On considère une fonction f définie sur l’intervalle [-α ; α] que l’on approche ainsi par un arc de parabole. En utilisant les polynômes d’interpolation de Lagrange, montrer que l’approximation polynomiale du second degré de f utilisée est alors définie par : f (-α) x−α x P(x) = ( 2α 2 ) f (0) x−α + ( -α ) (x+α) + f (α) x (x+α) 2α2 α [f(-α)+4f(0)+f(α)]. 3 On en déduit immédiatement, la contribution à l’aire de chaque subdivision : Montrer que l’intégrale de la fonction P sur [-α ; α] est égale à : 7 b−a x + xk+1 f(xk) + f(xk+1) + 4f k 6n 2 puis l’estimation suivante de l’aire globale : k=n ∑ b−a A3(n)= f(a) − f(b) + 2 6n k=1 Dans ce cas, en supposant f C4, une majoration de l'erreur est : (b−a)5 (4) 4 sup f 2880n k=n ∑ b−a f a + k +4 n b−a f a + (2k−1) 2n k=1 IV. EQUATIONS DIFFERENTIELLES : METHODE D'EULER. Cette partie et la suivante utilisent l'annexe algorithmique du rapport informatique et mathématique de la Commission de Réflexion sur l'Enseignement des Mathématiques http://smf.emath.fr/Enseignement/CommissionKahane/ En voici une citation : « Soit f une fonction réelle. On considère l'équation différentielle (1) y'(t) = f(y(t)), x≥0, y(0)=y0, La méthode d'Euler consiste à approcher la solution de (1) par la récurrence yk+1 = yk + hf(yk) Ici h est le pas de temps (destiné à tendre vers 0), et yk représente une approximation de y(kh). On a pris la même notation pour la solution de l'équation différentielle et son approximation, sans risque de confusion. On peut associer au pas h la fonction yh(t) définie en interpolant linéairement entre les points kh et (k + 1)h : { Quelquesoit k entier, yh(kh) = yk, yh affine sur [kh, (k + 1)h] On peut vérifier que si f est localement lipchitzienne, on a une estimation du type | yh(t) − y(t) | ≤ CTh, pour t ∈ [0, T] Au moins si T est assez petit. Nous admettons ce résultat » L'équation différentielle proposée en (1) est-elle la plus générale ? Proposer un algorithme permettant de calculer les yk, une fois f, y0 et h donnés. h Tracer la fonction y V. QUELQUES EXEMPLES D’ALGORITHMES EN ALGEBRE ET ARITHMETIQUE 1. Partie entière, fractionnaire, divisions euclidiennes, pgcd (référence) Analyser les algorithmes suivant et montrer qu'ils produisent le résultat attendu. Les programmer. Calcul de la partie entière : Entrées : a ≥ 0, réel Initialisation : α := a, n := 0 Tantque α ≥ 1 Faire (α,n) ← (α−1, n+1) Fintantque Rendre n, α Sorties : partie entière, partie décimale Un algorithme de division euclidienne de deux entiers. Entrées : a ≥ 0, b > 0, entiers. Initialisation : j := 0, α := a 8 Tant que α ≥ b f aire (α, j) ← (α − b, j + 1) Fintantque Rendre α, j Sorties : r, q entiers. Une forme de l'algorithme d'Euclide pour calculer un pgcd : Entrées : a ≥ 0, b ≥ 0, entiers. Initialisation : α := a, β := b Tant que α ≥ 0 et β ≥ 0 faire si β = 0 rendre α et sortir si 0 < β ≤ α faire (α,β) ← (α − β,β) si 0 ≤ α < β échanger (α,β) ↔ (β,α) Fintantque Sortie . pgcd (a,b), entier. Une forme de l'algorithme d'Euclide permettant de calculer, en plus, les coefficients de Bézout. Entrées : a ≥ 0, b ≥ 0, entiers. Autre écriture : Initialisation: α := a, β := b a 1 0 Initialisation : M := b 0 1 λ := 1, µ := 0 Tant que α ≥ 0 et β ≥ 0 faire ρ := 0, σ := 1 si β = 0 rendre M1,1, M1,2 et M1,3 sortir Tant que α ≥ 0 et β ≥ 0 faire si 0 < β ≤ α faire M← RM si β = 0 rendre (α, λ, µ) et sortir si 0 ≤ α < β échanger M↔ SM si 0 < β ≤ α faire (α,β, λ, µ, ρ, σ) ← (α − β, β, λ − ρ, µ − σ, ρ, σ) Fintantque Sortie : pgcd (a,b), u, v, entiers. si 0 ≤ α < β échanger (α,β, λ, µ, ρ, σ) ↔ (β,α, µ, λ, σ, ρ) Fintantque R et S à trouver… Sortie : pgcd (a,b), u, v, entiers. 2. Matrices, pgcd (Université de Reins) Analyser les algorithmes suivant et montrer qu'ils produisent le résultat attendu. Les programmer. Pour poursuivre le thème précédent, l'algorithme d'Euclide (avec divisions euclidiennes) produit la suite de divisions : 3164 = 3 × 819 + 707 (1) 819 = 1 × 707 + 112 (2) 707 = 6 × 112 + 35 (3) 112 = 3 × 35 + 7 (4) 35 = 5 × 7 + 0 (5) On en déduit classiquement le pgcd et les coefficients de Bézout. Le calcul des coefficients de Bézout n'est cependant pas explicite. On peut reformuler les cinq égalité ci-dessus en : 3164 3 1 819 112 3 1 35 = (4) (1) = 819 1 0 707 35 1 0 7 819 1 1 707 35 5 1 7 = (5) (2) = 707 1 0 112 7 1 0 0 On en déduit; de même; le pgcd. 707 6 1 112 = (3) 112 1 0 35 On a alors facilement : 3164 7 = M où M est inversible (déterminant égal à -1). 819 0 9 7 3164 Et donc 0 = M-1 819 . On a là : 7 = a × 3164 + b × 819 (où a et b sont des coefficients de M-1). Entrées : a ≥ 0, b ≥ 0, entiers. Initialisation: α := a, β := b, ρ := 0 1 0 0 1 Α := 0 1 , Β := 1 0 (E est la fonction partie entière) Tantque α − β × E(α/β) ≠ 0 Β1,1 ← E(α/β) Α ← ΑΒ ρ ← α − β × E(α/β) α←β β←ρ Fintantque Rendre β Α ← Α−1 Rendre Α2,1, Α2,2 Sortie : pgcd (a,b), u, v, entiers. Remarque : cet algorithme, et le suivant, ne travaillent pas exclusivement avec des entiers mais avec des nombres réels. 3. Développement en fractions continues (référence) Même question que pour le 1. L'algorithme suivant calcule les N premiers coefficients du développement en fraction continue de x : Entrées : x ≥ 0, réel ; N, entier Initialisation : j := 0, α := x Tantque j ≤ N et α non entier aj := E(α) 1 , j+1) (α,j) ← ( α − aj rendre aj Fintantque Sortie : a0, … , aN, entiers Une fois cet algorithme programmé on pourra se reporter à l'exemple préliminaire de la fiche calculatrice (I) (questions b) et f)). 4. Utilisation de listes Écrire un algorithme permettant, à partir d'un entier n, de donner la liste de ses diviseurs. Le programmer. Écrire un algorithme donnant une liste des diviseurs communs à 2 (ou plus) nombres donnés. On peut alors obtenir le pgcd : comparer avec l'algorithme d'Euclide. 10