Conditions
Booléens¶
Une valeur booléenne (bool
) est soit true (vrai) soit false (faux). Exemple de variable de type bool
:
let a = true
val a : bool = true
Comparaison¶
On peut tester l'égalité de deux valeurs avec =
:
3 = 1 + 2
- : bool = true
On peut aussi utiliser =
sur des variables, auquel cas on compare leurs valeurs :
let a = 3 in
let b = 4 in
a = b (* teste si les valeurs de a et b sont égales *)
- : bool = false
Attention : le =
de OCaml correspond au ==
de Python. ==
existe en OCaml, mais compare les adresses mémoires de 2 variables au lieu de leurs valeurs et on ne l'utilisera presque jamais.
On peut comparer des valeurs numériques avec <
(inférieur strict), >
, <=
(inférieur ou égal), >=
, <>
(différent)... :
2 < 1
- : bool = false
Il faut obligatoirement comparer des valeurs de même type :
2.4 < 3 (* on ne peut pas comparer un float avec un int *)
File "[3]", line 1, characters 6-7: 1 | 2.4 < 3 (* on ne peut pas comparer un float avec un int *) ^ Error: This expression has type int but an expression was expected of type float Hint: Did you mean `3.'?
2.4 < 3.0 (* par contre ceci fonctionne *)
- : bool = true
Remarque : pas besoin de mettre des points (.) sur <
, >
...
Les opérateurs &&
(et), ||
(ou), not
permettent de combiner des conditions :
1 < 2 && 2 < 3
- : bool = true
let a = 0 in
a <> 0 || a > 3 (* test si a est différent de 0 ou supérieur à 3 *)
- : bool = false
Exercice
- Quelle est la valeur du code suivant?
let a = 42 in not (a = 42 && (a < 10 || a > 30))
- Comment aurait-on pu écrire
not (a = 42 && (a < 10 || a > 30))
sansnot
? - Écrire une fonction
xor : bool -> bool -> bool
telle quexor a b
renvoie le "ou exclusif" dea
etb
, c'est à diretrue
sia
oub
esttrue
, mais pas les deux.
Solution
(* 1 *)
let a = 42 in
not (a = 42 && (a < 10 || a > 30));; (* false *)
(* 2 *)
(* Pour prendre la négation, on inverse toutes les conditions et opérateurs booléens (< devient >=, && devient || ...) *)
a <> 42 || (a >= 10 && a <= 30)
(* 3. *)
let xor a b = (a || b) && (not a || not b);;
xor true false;;
xor true true;;
- : bool = false
val xor : bool -> bool -> bool = <fun>
- : bool = true
- : bool = false
Condition if¶
On peut écrire une condition if
de la façon suivante en OCaml :
if ... then ... else ...
La condition du if
doit être un booléen. Si la condition est vraie, le then
est exécuté et sa valeur est renvoyé. Sinon, c'est la valeur du else
qui est renvoyé :
if 1 = 2 then 42 else 24
- : int = 24
Définissons par exemple la fonction valeur absolue ($x \longmapsto \vert x \vert$) :
let abs x =
if x < 0. then -. x
else x
val abs : float -> float = <fun>
Rappelons qu'il n'y a pas de return
en OCaml : c'est la dernière expression calculée par la fonction qui est renvoyée. Ainsi abs x
renvoie -x
si x
est négatif et x
sinon.
abs (-2.718) (* je mets des parenthèses à cause du - *)
- : float = 2.718
Pour plus de lisibilité on sautera une ligne avant then
et else
, sauf si le contenu du if
est très court.
Exercice
Écrire une fonction max
renvoyant le maximum de ses 2 arguments.
Remarque : cette fonction existe déjà et peut être utilisée telle quelle.
let max x y = if x < y then y else x
val max : 'a -> 'a -> 'a = <fun>
Dans un if ... then ... else ...
, les valeurs dans le then
et dans le else
doivent être de même type :
if 1 = 1 then 2
else 3.14 (* impossible d'avoir 2 types différents dans le then et else *)
File "[12]", line 2, characters 5-9: 2 | else 3.14 (* impossible d'avoir 2 types différents dans le then et else *) ^^^^ Error: This expression has type float but an expression was expected of type int
La valeur renvoyée par if ... then ... else ...
peut être stockée dans une variable :
let a = -5 in
let b = if a > 0 then a else -a in (* on pourrait aussi calculer une valeur absolue comme ça *)
b (* b vaut 5 *)
- : int = 5
Exercice
Définir les fonctions suivantes en OCaml :
Solution
let f1 x =
if x < 1. then 2. (* l'argument de f1 doit être un float donc il faut le comparer à un float *)
else 1.;;
let abs_float x = (* valeur absolue sur les entiers *)
if x < 0. then -.x else x;;
let f2 x =
if x < 0. then abs_float (x +. 3.)
else 3.;;
let f3 x =
if x < 0. then 0.
else if x < 1. then 1.
else 3.;;
val f1 : float -> float = <fun>
val abs_float : float -> float = <fun>
val f2 : float -> float = <fun>
val f3 : float -> float = <fun>
Exercice
Écrire une fonction n_solutions : float -> float -> float -> int
telle que n_solutions a b c
renvoie le nombre de solutions de l'équation $ax^2 + bx + c$.
Solution
let n_solutions a b c =
let delta = b**2. -. 4.*.a*.c in
if abs delta < 0.0001 then 1 (* regarde si delta vaut 0, en prenant en compte les erreurs d'arrondis des float *)
else if delta > 0. then 2
else 0;;
n_solutions 3. 5. 2.;;
val n_solutions : float -> float -> float -> int = <fun>
- : int = 2