Télécharger au format docx, pdf ou txt
Télécharger au format docx, pdf ou txt
Vous êtes sur la page 1sur 12

3 Les booléens

3.1 Le type des booléens

Ensemble des booléens : {vrai, faux} (deux valeurs).

Opérations sur les booléens non, et, ou (il y en a d’autres) :

– non : booléen −→ booléen définie par non(vrai) = faux et non(faux) = vrai

– et : booléen × booléen −→ booléen / ou : booléen × booléen −→ booléen

notations infixées : x et y et x ou y (plutôt que et(x, y) et que ou(x, y)).

Définies par

x y x et y x ou y

faux faux faux faux

faux vrai faux vrai

vrai faux faux vrai

vrai vrai vrai vrai

Type des booléens : booléen = ({vrai, faux}, non, et, ou).

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 :

si vrai alors a sinon s fin-si = a si faux alors a sinon s fin-si = s

Le résultat est donc aussi de type T.

Égalités importantes (notamment pour simplifier), pour x, y, z ∈ {vrai, faux} :

[1] non(vrai) = faux [2] non(faux) = vrai

[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

[14] x et(y ou z) = (x et y) ou(x et z) [15] x ou(y et z) = (x ou y) et(x ou z)

[7] : involutivité de non. [8] et [9] : lois de de Morgan. [10] et [11] : commutativité de et et de ou. [13]
et [14] : distributivité

de et sur ou et de ou sur et.

[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

vide, s’écrit : si c alors i1 fin-si.

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 reste de la division euclidienne de a par b est nul).

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

mod(·, ·) et si · alors · sinon · fin-si.

Écrire un autre algorithme de cette fonction, en utilisant mod(·, ·) et les opérations non, et et ou,
mais passi · alors ·sinon · fin-si.

3.2 Implantation des booléens en C

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

des raisons de lisibilité.

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

si a représente un réel nul.

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.

Le non s’écrit par le symbole !.

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 :

if (c) /* Noter que la condition est entre parenthèses */

instructions1 ; /* Noter que le `` alors '' est sous-entendu */

else

instructions2 ;

} /* Noter que le `` finsi '' est sous-entendu */

où instructions1 et instructions2 sont chacune une suite d’instructions en C. Si s est la suite


d’instructions vide,

alors, on peut se passer du else et faire :

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 ?

Écrire une fonction max4 qui calcule le maximum de quatre entiers.


Écrire une fonction mediane qui prend trois entiers en paramètres et, s’ils sont différents deux à
deux retourne la valeur

qui n’est ni le minimum, ni le maximum 1

. Par exemple mediane(2, -4, 8) retourne 2. On veut deux versions de cette

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

que 2004 et 2000 sont bissextiles.

Remarque : a % b est le reste de la division entière (euclidienne) de a par b.

4 Les entiers

4.1 Les entiers naturels

4.1.1 Type abstrait entier_nat

Intuition des « entiers bâtons ».

Nom du type : entier_nat.

Type abstrait importé : booléen.

Opérations primitives :

– Noms et profils :

– Constructeurs :

zéro : −→ entier_nat

succ : entier_nat −→ entier_nat

( Erreur_entier_nat :−→ entier_nat )

– Accès :

est_nul : entier_nat −→ booléen

préc : entier_nat −→ entier_nat

– Axiomes

[Ax-1] est_nul(zéro) = vrai


[Ax-2] est_nul(succ(x)) = faux

[Ax-3] préc(zéro) = Erreur_entier_nat()

[Ax-4] préc(succ(x)) = x

Opérations non primitives : il y en a une infinité.

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),

mult (x×y), div et mod (quotion et reste de la division euclidienne), puissance (x

), fact (x!), est_premier (x est-il

premier ?), pgcd (plus grand commun diviseur de x et y), somme_diviseurs_premiers (somme des
diviseurs premiers

de x et y, comptés avec leur ordre de multiplicité ou – version 2 – sans), somme_diviseurs (somme


des diviseurs de x

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.).

4.1.2 Démarche algorithmique et exemple

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.

Exemple du déroulement de la démarche sur un exemple : égaux.

(1) Profil. égaux : entier_nat × entier_nat −→ booléen .

(2) Exemples. Notation : SSS0 pour succ(succ(succ(zéro))).

égaux(SSS0, SSS0) = égaux(SS0, SS0) = égaux(S0, S0) = égaux(0, 0) = vrai

égaux(SSS0, SS0) = égaux(SS0, S0) = égaux(S0, 0) = faux


égaux(SSS0, SSSS0) = égaux(SS0, SSS0) = égaux(S0, SS0) = égaux(0, S0) = faux

(3) Axiomes (généralisés à partir des exemples).

[Ax-5] égaux(zéro, zéro) = vrai

[Ax-6] égaux(zéro, succ(x)) = faux

[Ax-7] égaux(succ(x), zéro) = faux

[Ax-8] égaux(succ(x), succ(y)) = égaux(x, y)

(4) Algorithme récursif (i.e., la fonction égaux fait appel à elle-même).

fonction égaux (x : entier_naturel, y : entier_naturel) : entier_naturel

Début

si est_nul(x) et est_nul(y)

alors retourner vrai

fin-si

si est_nul(x) /* forcément, y sera non nul */

alors retourner faux

fin-si

si est_nul(y) /* forcément, x sera non nul */

alors retourner faux

fin-si

retourner égaux (préc(x), préc(y))

Fin

On peut le simplifier (en passant éventuellement par plusieurs étapes).

fonction égaux (x : entier_naturel, y : entier_naturel) : entier_naturel

Début

si est_nul(x) ou est_nul(y)

alors retourner est_nul(x) et est_nul(y)

fin-si

retourner égaux (préc(x), préc(y))

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

at SSS0 SS0 S0 0 ← stop !

bt SSSS0 SSS0 SS0 S0

On peut utiliser la boucle de structure

tant que <booléen>

<instructions>

fin-tant que

qui exécute les instructions tant que le booléen est égal à vrai.

fonction égaux (x : entier_naturel, y : entier_naturel) : entier_naturel

Début

a := x

b := y

tant que non(est_nul(a)) et non(est_nul(b))

a := prec(a) /* opération licite car a est non nul */

b := prec(b) /* idem pour b */

fin-tant que

/* à cet endroit : a est nul ou b est nul (cf. lois de de Morgan)

si ce sont les deux qui sont nuls, alors x est égal à y : */

retourner est_nul(a) et est_nul(b)

Fin

Les commentaires peuvent être utiles pour rendre le programme plus lisible. On peut aussi utiliser x
et y directement à la

place de a et b, pour gagner deux lignes.

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

(voir section 4.1.3).

/* Test d'égalité de deux entiers naturels */

#include <stdbool.h>

#include "entier_naturel_batons.h"
/* Implantation récursive de l'opération égaux */

bool egaux_R (ENTIER_NAT x, ENTIER_NAT y)

if (est_nul (x) || est_nul (y))

return est_nul (x) && est_nul (y) ;

return egaux_R (prec (x), prec (y)) ;

/* Implantation itérative de l'opération égaux */

bool egaux_I (ENTIER_NAT x, ENTIER_NAT y)

ENTIER_NAT a, b ;

a=x;

b=y;

while (!est_nul (a) && !est_nul (b)) {

a = prec (a) ;

b = prec (b) ;

return est_nul (a) && est_nul (b) ;

void affiche_egalite (ENTIER_NAT x, ENTIER_NAT y) {

printf ("égaux (%d, %d) ? Par egaux_R : %d, par egaux_I : %d\n",

x, y, egaux_R (x, y), egaux_I (x, y)) ;

void test_egaux ()

affiche_egalite (3, 4) ;

affiche_egalite (4, 2) ;

affiche_egalite (6, 6) ;

affiche_egalite (0, 0) ;

int main ()
{

test_egaux () ;

L’exécution de ce code donne :

% gcc -o egaux egaux.c

% egaux

égaux (3, 4) ? Par egaux_R : 0, par egaux_I : 0

égaux (4, 2) ? Par egaux_R : 0, par egaux_I : 0

égaux (6, 6) ? Par egaux_R : 1, par egaux_I : 1

égaux (0, 0) ? Par egaux_R : 1, par egaux_I : 1

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 :

bool egaux_I (ENTIER_NAT x, ENTIER_NAT y)

while (!est_nul (x) && !est_nul (y)) {

x = prec (x) ;

y = prec (y) ;

return est_nul (x) && est_nul (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

valeur des variables u et v.

4.1.3 Implantation en C des entiers naturels

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 */

/* auteur : Jens Gustedt et Jean Lieber */

/* date : 22/09/09 */

/* version : 2 */

/*******************************************/

#include <stdio.h> /* Pour le printf */

#include <stdlib.h> /* Pour le exit */

typedef unsigned int ENTIER_NAT ;

/* Constructeurs */

#define ZERO 0

ENTIER_NAT succ (ENTIER_NAT x)

return 1 + x ;

ENTIER_NAT Erreur_entier_nat () {

printf ("Erreur de manipulation d'entier naturel.") ;

exit (EXIT_FAILURE) ;

return 0 ;

/* Accès */

ENTIER_NAT est_nul (ENTIER_NAT x)

return x == 0 ;

ENTIER_NAT prec (ENTIER_NAT x)

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

/* Implantation récursive de l'opération égaux, version 2 */

bool egaux_R (unsigned int x, unsigned int y)

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.

4.2 Les entiers relatifs

Les entiers relatifs (ou entiers signés) sont les éléments de ZZ : 0, 1, −1, 2, −2, 3, −3, etc.

4.2.1 Type abstrait

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 :

est_plus : signe −→ booléen

et les axiomes sont :

[Ax-9] est_plus(+) = vrai

[Ax-10] est_plus(-) = faux

(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 :

cons : signe × entier_nat −→ entier

les accès :

valeur_absolue : entier −→ entier_nat signe_de : entier −→ signe

et les axiomes

[Ax-11] valeur_absolue(cons(x, y)) = y

[Ax-12] signe_de(cons(x, y)) = x

Afin de gérer les erreurs, on peut également proposer le constructeur

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.

4.2.2 Implantation en C des 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 (==, !=, +, -, *, /, %, <, <=, >=, >).

Exercice 9 Écrire un algorithme et un programme C de la fonction abs qui à un entier associe sa


valeur absolue. Par

exemple, abs(4) et abs(-4) retournent tous deux la valeur 4.

Exercice 10 Écrire un algorithme et un programme C de la fonction signe qui à un entier n associe un


entier s tel que

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

algorithme et un programme C de cette suite.

Vous aimerez peut-être aussi