Chap. 2 : Expressions et boucles  

1. Éléments de syntaxe 

1.1 Constantes initialement définies 

Symbole usuel 

Nom Maple 

Valeur 

Pi 

Pi 

3.1416... 

i 

I 

 

 

infinity 

 

e 

e 

2.718 

gamma 

gamma 

0.577 

Ne pas confondre Pi avec pi : cette dernière variable est indéterminée. De façon générale, Maple distingue les lettres majuscules des lettres minuscules. Les variables initialement définies peuvent être modifiées par la commande unprotect : 

> evalf(Pi); unprotect(Pi); Pi:=55: evalf(Pi);
 

3.141592654 

55. 

1.2 Les fonctions usuelles 

La palette Expression habituellement sur la gauche de la feuille de travail (ou bien obtenues dans le menu View/Palettes) donne les fonctions élémentaires. En particulier il ne faut pas confondre le logarithme naturel avec le logarithme décimal : 

> 'ln(2.)' = ln(2.); 'ln(exp(1))' = ln(exp(1));
 

ln(2.) = .6931471806 

ln(exp(1)) = 1 

> 'log[10](2.)' = log[10](2.); 'log[10](10.)' = log[10](10.);
 

log[10](2.) = .3010299957 

log[10](10.) = 1. 

2. Suites, ensembles et listes 

Il ne faut pas confondre les suites, les ensembles et les listes 

2.1 Suites 

Les suites sont créées en séparant les objets par une virgule. Il faut respecter l'ordre : ainsi 1,2,3 est différent de 2,1,3. 

 

> restart: suite := 1,2,3,2,3;
 

1, 2, 3, 2, 3 

La fonction seq permet de créer facilement des suites : 

> seq(cos(i*Pi/6),i=1..3);
 

1/2*3^(1/2), 1/2, 0 

2.2 Ensembles 

Un ensemble est créé par une suite non ordonnée d'expressions distinctes et entourée par deux accolades, { et }. Ainsi l'ensemble {1,2,3}est égal à {2,3,1,1,3}. 

L'opérateur  evalb évalue si une expression est vraie ; avec la suite précédente, on vérifie l'égalité : 

> evalb( {suite} = {3,2,1} );
 

true 

2.3 Listes 

Une liste est créée par une suite ordonnée  d'expressions qui peuvent être identiques et entourée par deux crochets, [ et ].  Les listes peuvent être imbriquées les unes dans les autres.  

> liste_1 := [1,2,3];
liste_2 := [3,4,5];
liste_3 := [liste_1,liste_2];
 

[1, 2, 3] 

[3, 4, 5] 

[[1, 2, 3], [3, 4, 5]] 

Les éléments d'une liste (contenus entre les deux crochets) sont obtenus par l'opérateur op :  

> liste_4 := [op(liste_1),op(liste_2)];
 

[1, 2, 3, 3, 4, 5] 

le i-ème élément d'une liste est donnépar op(i,list). 

> op(5,liste_4);
 

4 

La liste_2 étant la liste précédente, on peut également obtenir un de ses éléments en donnant son rang entre crochets et on peut modifier la valeur de cet élément : 

> liste_2[3];
liste_2[3] := 67;
liste_2;
 

5 

67 

[3, 4, 67] 

Par contre on ne peut pas supprimer un élément d'une liste, par exemple en lui affectant la valeur  NULL qui est l'élément neutre des suites d'expressions. Pour supprimer un élément d'une liste, il faut utiliser la commande subsop 

 

> liste_2[2] := NULL;
 

Error, expression sequences cannot be assigned to lists 

> liste_n := subsop(2=NULL,liste_2);
liste_n;
 

[3, 67] 

[3, 67] 

3. Les conditionnelles 

3.1 Instruction conditionnelle  if then  .. else ..fi  

Les instructions conditionnelles sont très utilisées notamment pour faire des tests sur des variables. Exemple : faire un test pour savoir si un nombre entier y est pair ou impair et agir en conséquence. On utilisera la commande type : type(y, even) retourne vrai si y est pair et faux dans le cas contraire. La commande type(y,odd) fait l'inverse 

> y := 6: type(y, even);
 

true 

> y := 7: type(y, even); type(y, odd);
 

false 

true 

Avec cette commande on peut bifurquer d'un cas à l'autre avec if ... then ... else ... fi : 

> y := 18:
 

> if type(y, odd)    
    then print("y est impair");
    else print("y est pair");
fi;
 

 

3.2 Boucle conditionnelle : while 

La boucle while, exécutera les instructions qu'elle contient que tant que sa condition est remplie. Ainsi, il est parfois possible de ne jamais y entrer ! Ce type de boucle sera illustré à l'aide de la multiplication égyptienne. Pour multiplier deux nombres l'un par l'autre, soit x par y, les égyptiens multipliaient x par 2 et divisaient y par 2 quand y est pair ; si par contre y est impair, on ajoute x au résultat précédent et on retranche 1 de y qui de ce fait devient pair. On s'arrête quand y vaut 1. 

Ci dessous on multiplie 17 par 30 ce qui donne bien sûr 510 

> x := 17: y := 30: s := 0:
'x'=x,'y'=y,'résultat'=s;
while y>0 do
   if type(y,odd) then s:=s+x; y:=y-1;
        else x:=2*x; y:=y/2;
        fi;
   'x'=x, 'y'=y, 'résultat'=s;
od;
 

x = 17, y = 30, résultat = 0 

x = 34, y = 15, résultat = 0 

x = 34, y = 14, résultat = 34 

x = 68, y = 7, résultat = 34 

x = 68, y = 6, résultat = 102 

x = 136, y = 3, résultat = 102 

x = 136, y = 2, résultat = 238 

x = 272, y = 1, résultat = 238 

x = 272, y = 0, résultat = 510 

4. Fractions continues 

Le développement en fraction continue d'un nombre r est donné par la relation : 

 

a[0] est la partie entière de r (en Maple trunc(r))  et le reste est sa partie fractionnaire (en Maple frac(r)). Les éléments réduits (mis sous la forme numérateur/dénominateur) de la  suite 

 

fournissent des approximations rationnelles successives (convergents} de r. On montre assez facilement que si r est un rationnel, cette suite est finie ; par contre, elle est infinie si r est irrationnel. En Maple, après avoir chargé la bibliothèque numtheory  par la commande with(numtheory), le développement en fraction continue est obtenu par  cfrac(r,n) où n désigne éventuellement l'ordre du dernier convergent ; par exemple, le développement en fraction continue de 17/23 (par défaut jusqu'au dixième ordre,  en fait, c'est un rationnel et n=5) est donné par : 

> restart: with(numtheory): '17/23' = cfrac(17/23);
 

17/23 = CFRAC([0, 1, 2, 1, 5]) 

La liste des entiers dans les dénominateurs est obtenue par la commande convert(r,confrac) et la liste des convergents  peut être mise dans un troisième argument (optionnel) 

 

> `liste des a_i` = convert(17/23,confrac,convergents);
'convergents' = convergents;
 

`liste des a_i` = ([0, 1, 2, 1, 5]) 

convergents = ([0, 1, 2/3, 3/4, 17/23]) 

Si on change 17/23 par 25/23, on obtient un message d'erreur : 

> `liste des a_i` = convert(25/23,confrac,convergents);
 

Error, (in convert/confrac/numeric) invalid arguments 

Le premier appel à  convert a donné une  valeur à la variable convergents et le second appel à la même commande ne peut plus changer cette valeur. Il faut libérer la variable de cette valeur (vider la mémoire, ou plutôt la rendre disponible en l'entourant de deux cotes).  

D'où cette remarque très générale  : entourer une variable entre des accents aigus (') permet d'appeler le  nom de la variable et non sa  valeur. Pour libérer la valeur d'une variable, on affecte son nom à la valeur de la variable par : 

variable := 'variable'; 1 

Bien suivre les opérations suivantes : 

> n := 15;       # On met le nombre 15 dans la mémoire d'adresse n
n;             # On vérifie le contenu de la mémoire
n := 'n';      # Le contenu de la mémoire est écrasée
n;             # La mémoire d'adresse n est vide
 

15 

15 

n 

n 

> `liste des a_i` = convert(25/23,confrac,'convergents'); 'convergents' = convergents;
 

`liste des a_i` = ([1, 11, 2]) 

convergents = ([1, 12/11, 25/23]) 

Les commandes données ci-dessous seront exécutées pour analyser trois types de nombres.
 

1 - L'expression evalf(17/23,20) donne une approximation à vingt chiffres significatifs du nombre rationnel 17/23 ; donc c'est aussi un nombre rationnel : son développement en fraction continue sera comparé avec celui de 17/23 ci-dessus. 

> `approximation de 17/23` = evalf(17/23,20);
 

`approximation de 17/23` = .73913043478260869565 

> 'evalf(17/23)' = cfrac(evalf(17/23,20));
 

evalf(17/23) = CFRAC([0, 1, 2, 1, 4, 1, 869565217391304347]) 

> `liste des a_i` = convert(evalf(17/23,20),confrac,'convergents');
'convergents' = convergents;
 

`liste des a_i` = ([0, 1, 2, 1, 4, 1]) 

convergents = ([0, 1, 2/3, 3/4, 14/19, 17/23]) 

2 -   Pi est un nombre irrationnel : la suite de ses convergents  est une suite infinie non périodique. 

 

> 'Pi' = cfrac(Pi);
 

Pi = CFRAC([3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, `...`]) 

> `liste des a_i` = convert(Pi,confrac,'convergents');
'convergents' = convergents;
 

`liste des a_i` = ([3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3]) 

convergents = ([3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317, 312689/99532, 833719/265381, 1146408/364913, 4272943/1360120])
convergents = ([3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317, 312689/99532, 833719/265381, 1146408/364913, 4272943/1360120])
 

3 - La racine carrée d'un polynôme du deuxième degré est un nombre irrationnel : on vérifie que la suite de ses convergents  est infinie et périodique. La commande  solve donne les solutions par rapport à la variable -donnée en deuxième argument- de l'expression donnée en premier argument qui, sauf précision contraire, est supposée par défaut être égale à zéro. 

> solutions := solve(x^2+7*x+2,x);
 

-7/2+1/2*41^(1/2), -7/2-1/2*41^(1/2) 

On prend la première racine : 

> x1 := solutions[1];
 

-7/2+1/2*41^(1/2) 

> 'x1' = cfrac(x1);
 

x1 = CFRAC([-1, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, `...`]) 

Remarquer que ci-dessous, on obtient la partie entière plus 10 éléments de la partie fractionnaire: 

> `liste des a_i` = convert(x1,confrac,'convergents');
'convergents' = convergents;
 

`liste des a_i` = ([-1, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5]) 

convergents = ([-1, 0, -1/3, -2/7, -3/10, -17/57, -20/67, -57/191, -134/449, -191/640, -1089/3649])
convergents = ([-1, 0, -1/3, -2/7, -3/10, -17/57, -20/67, -57/191, -134/449, -191/640, -1089/3649])
 

Par contre cidessous on a la partie entière plus 30 éléments et une périodicité plus évidente : 

> cfrac(x1,30,'quotients');
 

[-1, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, `...`]
[-1, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, 1, 2, 2, 1, 5, `...`]
 

5. Bases et codage 

5.1. Opérateur convert 

Les nombres sont écrits ou pensés dans différentes bases, c'est-à-dire par paquets, puis paquets de paquets, etc.  Certes, la  base décimale est maintenant la plus utilisée, mais on groupe toujours les minutes par 60 pour faire des heures, les oeufs par boîtes  de 12, le quart de beurre correspond à un huitième de kilo, etc. Cette manière de grouper est devenue tout à fait inconsciente sauf quand pour régler 34 euros vous donnez trois billets de 10 euros et quatre pièces de 1 euro. Maple permet cette analyse par la commande convert(x,base,n) qui retourne une liste du type [ unité, dizaine, centaine, ... ], c'est-à-dire  que x est écrit dans un système de base n sous la forme  

 

> restart: liste := convert(753,base,10);
 

[3, 5, 7] 

le nombre de termes de cette liste est obtenu par la commande nops : 

> nops(liste);
 

3 

5.2 Instruction d'itération  for 

L'instruction  for permet d'exécuter de manière répétée une instruction (ou un bloc d'instructions), toujours entre do et od (mots réservés),  en modifiant la valeur d'une variable de contrôle puis en la comparant à une valeur limite avant chaque début de boucle. Par exemple, l'instruction suivante permet d'imprimer les nombres de 7 en 7, à partir de 4 et jusqu'à 30  

> for i from 4 by 7 to 30 do
   print(i)
od;
 

4 

11 

18 

25 

Reconstruire un nombre en base 10  à partir de la liste fournie par  convert : 

> liste:=convert(753,base,10);
 

[3, 5, 7] 

Il faut d'abord initialiser les variables : 

> resul := 0; ni := 1;
 

0 

1 

Remarquer la simplicité du déroulement avec la commande for element in liste ; ici on n'a pas besoin d'une variable supplémentaire de contrôle : 

> for element in liste do
        resul := resul + element*ni;
        ni := ni*10:
        print('resul' = resul)
od:
 

resul = 3 

resul = 53 

resul = 753 

5.3 Boucles imbriquées 

Imbriquer des boucles itératives for ou conditionnelles while est une pratique très courante en programmation. Par exemple, en utilisant les paragraphes précédents, on écrit le programme suivant qui compte le nombre de nombres écrits en base dix, compris entre 1 et 715 et où ne figure pas le chiffre 3 ; on doit trouver 499 : 

> total := 0:
for nombre to 715 do
    liste:=convert(nombre,base,10):
    a_garder:=true:  
    for ii to nops(liste) do
         if liste[ii]=3 then
              a_garder:=false:
         fi;
    od:
    if a_garder then
         total := total+1:
    fi:
od:
total;
 

499 

5.4 Codage binaire 

La décomposition des nombres en base 2 (base binaire)  est particulièrement importante en informatique : on ou off !  Bien observer la décomposition binaire des 8 premiers nombres : 

> restart:
for i to 8 do
   i = convert(i,base,2);
od;
 

1 = [1] 

2 = ([0, 1]) 

3 = ([1, 1]) 

4 = ([0, 0, 1]) 

5 = ([1, 0, 1]) 

6 = ([0, 1, 1]) 

7 = ([1, 1, 1]) 

8 = ([0, 0, 0, 1]) 

Montrer que [0,1,0,0,0,1] représente le nombre décimal 34. 

> liste := [0,1,0,0,0,1]:
resul :=0:
ni := 1:
for element in liste do
    resul := resul+element*ni;
    ni := ni*2:
    print(resul)
od:
 

0 

2 

2 

2 

2 

34 

Exercices simples 

2.1 (n-1)^2 et  `*`(2., n-1)  s'écrivent respectivement ab et ba 

En base n,  les nombres N= (n-1)^2 et P=2.(n-1) s'écrivent respectivement ab et ba.  Le vérifier tout d'abord pour n=9 et n=60. Ce résultat est  général.   Si on écrit 2*(n-1) sous la forme  n-2 + n, le chiffre des unités en base n apparaît être nécessairement égal à n-2 et celui des dizaines est égal à 1. 

Faire calculer alors dizaine +  unité*n, c'est-à-dire 1 + (n-2)*n,  on trouve bien évidemment (n-1)^2. 

> restart: N := (n-1)^2;  P := 2*(n-1);
 

(n-1)^2 

2*n-2 

> n := 9: convert(N,base,n); convert(P,base,n);
 

[1, 7] 

[7, 1] 

> n := 60: convert(N,base,n); convert(P,base,n);
 

[1, 58] 

[58, 1] 

> n := 'n': s := 1+(n-2)*n; factor(s);
 

1+(n-2)*n 

(n-1)^2 

2.2 (n-1)^3et (n+2)*(n-1)^2 s'écrivent avec les mêmes chiffres 

Dans un système de base n (n>3), les nombres Q=(n-1)^3 et R=(n+2).(n-1)^2 s'écrivent avec les mêmes chiffres. Le vérifier pour différentes valeurs de n puis faire un raisonnement général comme ci-dessus avec en plus des centaines. 

 

> restart: Q := (n-1)^3; R := (n+2)*(n-1)^2;
 

(n-1)^3 

(n+2)*(n-1)^2 

> n := 9: convert(Q,base,n); convert(R,base,n);
 

[8, 2, 6] 

[2, 6, 8] 

> n := 60: convert(Q,base,n); convert(R,base,n);
 

[59, 2, 57] 

[2, 57, 59] 

> n := 'n': s :=  n-1+2*n+(n-3)*n^2: factor(s);
 

(n-1)^3 

2.3 Couple de nombres premiers jumeaux 

Ecrire une boucle sur n variant de 1 à 10 dans laquelle on déterminera si les nombres premiers (donnés par  ithprime(i)), successifs et plus petits que n, divisent exactement n  ; mettre ces nombres premiers dans une liste. Utiliser ce type de commandes pour déterminer le plus petit couple de nombres premiers jumeaux (c'est à dire de la forme (p, p+2) supérieurs à 30 000. 

> restart:
for n from 1 to 10 do
    i := 1:
    liste := NULL:
    while ithprime(i)<n do
         if irem(n,ithprime(i))=0 then liste := ithprime(i), liste: fi:
         i := i+1:
    od:
    print('n' = n,'   liste' = liste):
od:
 

n = 1, liste =  

n = 2, liste =  

n = 3, liste =  

n = 4, liste = 2 

n = 5, liste =  

n = 6, liste = (3, 2) 

n = 7, liste =  

n = 8, liste = 2 

n = 9, liste = 3 

n = 10, liste = (5, 2) 

On cherche le premier nombre premier supérieur à 30000 : 

> i := 1:
while ithprime(i)<30000 do i := i+1: od:
idep:=i;
 

3246 

Recherche des nombres premiers jumeaux supérieurs à 30 000 : 

> i := idep:
while (ithprime(i)-ithprime(i-1)>2) do
    i := i+1:
od:
p := ithprime(i);
q := ithprime(i-1);
 

30013 

30011