Académique Documents
Professionnel Documents
Culture Documents
Exposé 1
Exposé 1
Définies par
x y x et y x ou y
Opération si alors sinon fin-si : trois paramètres (c, a, s) où c est un booléen et a et s sont tous deux
de type T (p. ex.,
deux entiers, deux booléens, deux réels, etc.). si alors sinon fin-si(c, a, s) se note si c alors a sinon s
fin-si. Défini par :
[3] x et vrai = x [4] x et faux = faux [5] x ou vrai = vrai [6] x ou faux = x
[7] non(non(x)) = x [8] non(x et y) = non(x) ou non(y) [9] non(x ou y) = non(x) et non(y)
[10] x et y = y et x [11] x ou y = y ou x
[12] si x alors y sinon z fin-si = (x et y) ou(non(x) et z) [13] si x alors vrai sinon faux fin-si = x
[7] : involutivité de non. [8] et [9] : lois de de Morgan. [10] et [11] : commutativité de et et de ou. [13]
et [14] : distributivité
[1] à [11] : à connaître absolument. [12] : à retrouver (ne s’applique que si T = booléen). [13] :
exemple d’application
de [6].
si c alors i1 sinon i2 fin-si où i1 et i2 sont des instructions, plutôt que des valeurs. Cas particulier où i2
est l’instruction
Exercice 1 Étant donné deux entiers naturels a et b, avec b 6= 0, « a est divisible par b » peut s’écrire
mod(a, b) = 0 (i.e.,
Le numéro d’une année bissextile est un nombre a qui est divisible par 4, à l’exception des multiples
de 100, sauf les
multiples de 400. Ainsi 2008 et 2000 sont des (numéros d’)années bissextiles, mais pas 2010 ni 1900.
Écrire l’algorithme de la fonction testant si un entier naturel donné est le numéro d’une année
bissextile, en utilisant
Écrire un autre algorithme de cette fonction, en utilisant mod(·, ·) et les opérations non, et et ou,
mais passi · alors ·sinon · fin-si.
Le type booléen est défini dans la bibliothèque standard stdbool.h. Autrement dit, si on veut
manipuler des booléens,
on écrira :
#include <stdbool.h>
Cela permet de définir le nom du type (bool) et les constantes true et false (traduisant,
respectivement, vrai et faux).
Remarque 1 En fait, en C, le type booléen n’est pas implanté en tant que tel : un booléen est
représenté par un entier : si
b est une variable de type entier, b correspondra à la valeur faux si b vaut l’entier 0 et à vrai sinon.
Traditionnellement,
on prend 1 comme valeur pour vrai. Cela dit, il vaut mieux utiliser le type bool et les constantes true
et false pour
Le ou s’écrit ||. Il ne coïncide pas exactement avec le ou logique parce que calculé de façon «
progressive ». Cela signifie
que si on effectue l’instruction exp = exp1 || exp2 ;, alors, l’expression exp1 est calculée en premier
et, si elle vaut
vrai, l’expression exp2 n’est pas évaluée. En effet, on a toujours vrai ou x = vrai, quelle que soit la
valeur du booléen
x. Ce calcul progressif permet d’une part de diminuer le temps de calcul et d’autre part d’éviter que
le programme fasse
des erreurs dans certains cas. Par exemple, l’expression (a == 0. || 1. / a < 3.) ne provoquera pas
d’erreur, même
Le et s’écrit && et est évalué de façon progressive. Si on a l’instruction exp = exp1 && exp2 ;, alors
exp1 sera évalué
en premier et si le résultat est faux, l’évaluation de exp2 n’est pas effectuée : faux et x = faux, quelle
que soit la valeur
de x.
si c alors a sinon s fin-si s’écrit avec la syntaxe suivante : c ? a : s. Il existe aussi un si · alors · sinon ·
fin-si dont
les parties conclusions (a ou s) sont des instructions et qui est très utilisé. Sa syntaxe est la suivante :
else
instructions2 ;
if (c)
instructions1 ;
Exercice 2 Écrire la procédure afficheBooleen qui affiche la valeur d’un booléen (affichage de vrai ou
de faux).
Exercice 3 Écrire une fonction max qui calcule le maximum de deux entiers (int).
Comment modifier cette fonction en une fonction min qui calcule le minimum de deux entiers ?
fonction, l’une utilisant une conditionnelle et l’autre utilisant d’autres fonctions déjà définies
auparavant.
Exercice 4 Écrire une procédure qui résout sur IR les équations du second degré (affichage des
solutions).
Exercice 5 Écrire une fonction qui teste si une année est bissextile ou non. Les années sont
généralement non bissextiles,
à l’exception des années divisibles par 4 (dont le numéro est divisible par 4). Les années divisibles par
100 sont une
exception à cette exception, sauf celles qui sont divisibles par 400. Ainsi 2003, 1900 et 2100 sont non
bissextiles, alors
4 Les entiers
Opérations primitives :
– Noms et profils :
– Constructeurs :
zéro : −→ entier_nat
– Accès :
– Axiomes
[Ax-4] préc(succ(x)) = x
Pour spécifier (profil et axiomes) et implanter (algorithes et programmes) une opération non
primitive, on peut s’appuyer
sur les opérations primitives ou sur les opérations non primitives déjà définies (ou introduites pour
les besoins de la cause).
Exemples d’opérations non primitives : égaux (x = y ?) plus_petit_que (x < y ?), plus (x + y), moins (x −
y),
premier ?), pgcd (plus grand commun diviseur de x et y), somme_diviseurs_premiers (somme des
diviseurs premiers
et y), carré (carré de x), est_carré (x est-il un carré parfait ?), racine_carrée (partie entière de √
x), n
ème_premier
(le 0
ème étant 2, le 1
er étant 3, etc.).
Pour une opération non primitive donnée, l’exercice consiste à (1) définir le profil, (2) traiter un ou
plusieurs exemples,
(3) définir des axiomes, (4) traduire ces axiomes en un algorithme récursif, (5) donner un algorithme
itératif, (6) traduire
l’algorithme récursif en C, (7) traduire l’algorithme itératif en C, (8) tester les fonctions C.
Début
si est_nul(x) et est_nul(y)
fin-si
fin-si
fin-si
Fin
Début
si est_nul(x) ou est_nul(y)
fin-si
Fin
(5) Algorithme itératif (i.e., sans appel récursif). Utilisation de variables et de structures de boucle.
Considérer à nouveau
l’exemple, en introduisant des variables. Par exemple, pour le calcul de égaux(SSS0, SSSS0) :
t0123
<instructions>
fin-tant que
qui exécute les instructions tant que le booléen est égal à vrai.
Début
a := x
b := y
fin-tant que
Fin
Les commentaires peuvent être utiles pour rendre le programme plus lisible. On peut aussi utiliser x
et y directement à la
Pour bien comprendre ce que fait l’algorithme, il faut le tester avec des exemples.
(6), (7) et (8). Le code C suivant répond aux questions (6), (7) et (8), respectivement par les fonctions
egaux_R, egaux_I et
la procedure test_egaux. Il suppose qu’existe une implantation des entiers naturels dans un fichier
entier_naturel_batons.h
#include <stdbool.h>
#include "entier_naturel_batons.h"
/* Implantation récursive de l'opération égaux */
ENTIER_NAT a, b ;
a=x;
b=y;
a = prec (a) ;
b = prec (b) ;
printf ("égaux (%d, %d) ? Par egaux_R : %d, par egaux_I : %d\n",
void test_egaux ()
affiche_egalite (3, 4) ;
affiche_egalite (4, 2) ;
affiche_egalite (6, 6) ;
affiche_egalite (0, 0) ;
int main ()
{
test_egaux () ;
% egaux
sachant que 0 signifie faux et 1 signifie vrai, le résultat correspond aux attentes.
Remarque 2 On pourrait réécrire la fonction egaux_I sans introduire de variables, en utilisant les
paramètres comme
variables :
x = prec (x) ;
y = prec (y) ;
Cela est possible parce qu’on fait un passage de paramètre par valeurs : l’appel egaux_I (u, v) pour u
et v deux
variables de type ENTIER_NAT valant respectivement 4 et 8 revient à l’appel egaux_I (4, 8) et donc ne
modifie pas la
Les entiers naturels sont représentés par plusieurs types en C dont le plus classique est le type
unsigned int (il y a aussi
unsigned short int et unsigned long int). On peut proposer l’implantation suivante du type
entier_nat :
/*******************************************/
/* entier_naturel_batons.h */
/* date : 22/09/09 */
/* version : 2 */
/*******************************************/
/* Constructeurs */
#define ZERO 0
return 1 + x ;
ENTIER_NAT Erreur_entier_nat () {
exit (EXIT_FAILURE) ;
return 0 ;
/* Accès */
return x == 0 ;
if (x == 0)
return Erreur_entier_nat () ;
return x - 1 ;
}
À terme, on n’utilisera directement les notations de C pour programmer les opérations sur les entiers
naturels (mais pas
avant de maîtriser l’autre façon de faire). Par exemple, la fonction egaux_R sera réécrite
if (x == 0 || y == 0)
return x == 0 && y == 0 ;
return egaux_R (x - 1, y - 1) ;
Et, en fait, on utilisera directement == pour tester l’égalité de deux entiers naturels.
Les entiers relatifs (ou entiers signés) sont les éléments de ZZ : 0, 1, −1, 2, −2, 3, −3, etc.
On peut définir un entier relatif par la donnée de son signe (sachant qu’il existe deux signes : + et −)
et de sa valeur
absolue. Deux entiers relatifs seront égaux soient si leurs valeurs absolues sont toutes deux nulles
(quels que soient leurs
signes : −0 = +0) soit s’ils ont même signe et même valeur absolue.
Avant d’introduire le type abstrait entier, nous allons introduire le type abstrait signe. Les
constructeurs de signe sont :
+ : −→ signe
- : −→ signe
l’accès est :
(au passage, on voit une façon de décrire l’axiomatique d’un ensemble à deux éléments).
Le type abstrait entier correspond à l’anneau (ZZ, +, ·) : les entiers de ce type sont des entiers « signés
». Ses types
importés sont booléen, entier_nat et signe. L’idée est qu’un entier est donné par un signe et un
entier_nat : 2
est donné par + et succ(succ(zéro)), −1 est donné par - et succ(zéro) et 0 est donné par + et zéro ou -
et zéro. On
propose le constructeur :
les accès :
et les axiomes
Erreur_entier : −→ entier
Exercice 7 On peut définir sur entier les opérations correspondant aux opérations zéro, succ, est_nul,
préc, égaux,
plus_petit_que, plus, moins, mult, div et mod de entier_nat. On utilisera les mêmes noms
d’opérations.
Pour chacune de ces opérations sur les entiers relatifs, donner le profil et un jeu d’axiomes.
Exercice 8 Donner un jeu d’axiomes pour l’opération testant l’égalité de deux entiers relatifs.
Le type C le plus classique pour représenter les entiers relatifs est int. Il y a aussi short et long. Les
opérations classiques
sur les entiers non signés s’appliquent ici (==, !=, +, -, *, /, %, <, <=, >=, >).
n = s × abs(n).
Exercice 11 Soit la suite (un) telle que u0 = 0, u1 = 1, u2 = −1, u3 = 2, u4 = −2, u5 = 3, u6 = −3, etc.
Écrire un