\chapter{Types et valeurs de base}
\label{chap-types-valeurs-base}

En programmation informatique, il existe plusieurs types de variables. 

Nous allons voir dans ce chapitre les types élémentaires.

\section{Représentation binaire d'un entier}

\begin{exointro}{\null}
On dispose d'une mémoire de 8 bits.
\begin{questions}
\item Donner le complément à 2 du nombre 78.
\item Donner le complément à 2 du nombre $-111$.
\item Donner alors le complément à 2 de la somme des nombres 78 et $-111$.
\item Vérifier que le nombre binaire trouvé est bien la somme de ces deux nombres.
\end{questions}
\end{exointro}


\begin{defin}
Soit $\overline{x_nx_{n-1}x_{n-2}\cdots x_1x_0}^{\;2}$ la représentation binaire d'un entier naturel.
\begin{itemize}
\item Le bit de rang 0, c'est-à-dire $x_0$, est appelé le \textit{bit de poids faible}.
\item Le bit de rang $n$, c'est-à-dire $x_n$, est appelé le \textit{bit de poids fort}.
\end{itemize}
\end{defin}

\subsection{Représentation binaire d'un entier naturel}

Nous avons vu dans le chapitre précédent qu'un entier naturel pouvait être codé en binaire.

\begin{defin}
On nomme \textit{binaire pur} le codage dans lequel sont écrits les entiers naturels.
\end{defin}

\begin{Exemple}
le nombre décimal $123$ peut être codé en binaire par $1111011$. 
\end{Exemple}

Ainsi, avec une mémoire de $n$ bits, tous les entiers de 0 à $2^n-1$ seront représentés. Par exemple,
\begin{itemize}
\item avec une mémoire de 8 bits, on peut coder tous les entiers naturels de 0 à 255;
\item avec une mémoire de 16 bits, on peut coder tous les entiers naturels de 0 à \numprint{65535};
\item avec une mémoire de 32 bits, on peut coder tous les entiers naturels de 0 à \numprint{4294967295};
\item avec une mémoire de 64 bits, on peut coder tous les entiers naturels de 0 à \numprint{18446744073709551615}.
\end{itemize}


\subsection{Représentation binaire d'un entier relatif}

\subsubsection{Le binaire signé}

\begin{defin}
On nomme \textit{binaire signé} le codage dans lequel sont écrits les entiers relatifs.
\end{defin}

Dans la représentation en binaire signé, le bit de poids fort sert à représenter le signe (\og 0 \fg{} pour un entier positif et \og 1 \fg{} pour un entier négatif), les autres bits représentent le nombre (sans le signe) en binaire pur. 
  
\begin{Exemples}
\begin{itemize}
\item $\base{01011001}{2}$ est la représentation en binaire signé du nombre $\base{89}{10}$ avec une mémoire de 8 bits.
\item $\base{11011001}{2}$ est la représentation en binaire signé du nombre $\base{-89}{10}$ avec une mémoire de 8 bits.
\end{itemize}
\end{Exemples}

Ainsi, avec une mémoire de $n+1$ bits, tous les entiers relatifs de $-(2^n-1)$ à $2^n-1$ seront représentés. Par exemple,\enlargethispage*{2em}
\begin{itemize}
\item avec une mémoire de 8 bits, on peut coder tous les entiers naturels de $-127$ à 127;
\item avec une mémoire de 16 bits, on peut coder tous les entiers naturels de $-\numprint{32768}$ à \numprint{32768};
\item avec une mémoire de 32 bits, on peut coder tous les entiers naturels de\linebreak $-\numprint{2147483647}$ à \numprint{2147483647};
\item avec une mémoire de 64 bits, on peut coder tous les entiers naturels de\linebreak $-\numprint{9223372036854775807}$ à \numprint{9223372036854775807}.
\end{itemize}

\begin{Remarque}
le nombre zéro est représenté dans cette convention (dites du \textit{zéro positif}) par : 0000...00000.

Remarquez alors que l'état binaire $\underbrace{1000\ldots000}_{n\text{ bits}}$ ne représente rien \textit{a priori}. 

\Par

Cependant, les informaticiens ont tout de même décidé qu'il représentait le nombre $-2^n$.
\end{Remarque}

Fort de cette dernière remarque, l'intervalle de représentation se trouve alors\linebreak augmenté d'un nombre; il devient : $\llbracket -2^n~;~2^n -1\rrbracket$. 

Dans la pratique, nous n'utilisons pas ce dernier codage. En effet, le traitement spécifique du signe coûte cher en circuits électroniques et en temps de calcul. 

On utilise plutôt une version améliorée : le complément à 2.

\subsubsection{Le complément à 2}

Ce codage est légèrement plus complexe que le binaire signé. 

\begin{methode}\label{complement-a-deux}
Soit $n$ un nombre exprimé en base 10; on cherche son complément à 2.

\begin{questions}
\item si $n>0$, on utilise le binaire signé ;

\item si $n<0$, 
\begin{itemize}
\item on code $|n|$ en binaire signé (c'est-à-dire $n$ sans son signe),
\item on prend le complément à 1 du binaire trouvé (c'est-à-dire que l'on remplace tous les 0 par des 1, et tous les 1 par des 0),
\item on additionne 1 au nombre binaire ainsi obtenu.
\end{itemize}
\end{questions}
\end{methode}

\begin{Exemple}
on souhaite trouver le complément à 2 de  $\base{-57}{10}$ avec une mémoire de 8 bits. Il est négatif donc :
\begin{itemize}
\item on commence par coder le nombre sans son signe en binaire signé, et on obtient : $\base{00111001}{2}$;
\item on prend le complément à 1, et on obtient : $\base{11000110}{2}$;
\item on ajoute 1 au binaire obtenu, et on obtient : $\base{11000111}{2}$.
\end{itemize}
\end{Exemple}

\begin{Remarques}
\begin{itemize}
\item L'opération consistant à prendre le complément de chaque bit est appelée le \textit{non logique} :
\begin{center}
non 0 = 1\qquad et \qquad non 1 = 0.
\end{center}
\item C'est de la dernière opération que le codage tire son nom : le fait d'ajouter 1 au binaire s'appelle \og prendre le complément à 2 \fg.
\end{itemize}
\end{Remarques}

\begin{attention}
En binaire, si ajouter 1 à 0 donne 1, ajouter 1 à 1 donne 10.
\end{attention}

L'avantage du complément à 2 se trouve dans les opérations sur les entiers (voir paragraphe \ref{somme-entiers}).

\begin{aretenir}
Avec une mémoire de 8 bits, le complément à 2 du nombre $-128$ est $\base{10000000}{2}$.\label{complementmoins128}
\end{aretenir}


\subsubsection{Entiers de taille arbitraire}

Faisons une petite expérience : ouvrons la console Python, et affectons à la variable x le plus grand entier possible, puis affichons la valeur de x :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&x = 0x7fffffffffffffff\\
&print(x)
\end{tabularx}

\Par

La console affiche alors : 
\begin{center}
\texttt{9223372036854775807}.
\end{center}

Maintenant, demandons d'ajouter 1 à x :

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&x + 1
\end{tabularx}

La console affiche :
\begin{center}
\texttt{9223372036854775808}.
\end{center}

Que s'est-il passé ? \texttt{x} est sensé être le plus grand entier... et pourtant, \texttt{x+1} existe !

En fait, Python a détecté le dépassement de capacité et il décide de ne plus représenter le résultat comme un entier mais comme un \textit{entier long}. Et contrairement au complément à 2, cette représentation n'est pas limitée en taille. Cela peut paraître intéressant comme représentation, mais elle a des inconvénients. Par exemple, les opérations sur les entiers longs prennent plus de temps que celles sur les entiers relatifs représentés en complément à 2.

La représentation des entiers longs étant bien plus complexe que le complément à 2, nous ne la traiterons pas ici.

\newpage

\subsection{Addition et soustraction de deux entiers}
\label{somme-entiers}

Que ce soit pour additionner ou pour soustraire, on utilise le complément à 2.

\subsubsection{Addition}

La règle d'or pour additionner en binaire est de retenir, comme nous l'avons vu précédemment, que $1+1=10$.

\begin{Exemple}
on souhaite additionner $-91$ et 113 avec un codage sur 8 bits. On peut donc coder tout nombre entre $-128$ et $127$.
\begin{itemize}
\item Le complément à 2 de $\base{-91}{10}$ est : $\base{10100101}{2}$.
\item Le complément à 2 de $\base{113}{10}$ est : $\base{01110001}{2}$.
\end{itemize}
On pose l'opération :
\[
\begin{array}{*{11}{c}}
 & &1&0&1&0&0&1&0&1\\
+& &0&1&1&1&0&0&0&1\\
\hline
&1& 0& 0& 0& 1& 0& 1& 1 & 0
\end{array}
\]
On ne garde que les 8 derniers bits :  00010110.

Le bit de poids fort étant 0, le résultat est positif. Ce dernier représente donc $\base{00010110}{2}=\base{22}{10}$.
\end{Exemple}

\subsubsection{Opposé d'un nombre}

Voyons sur un exemple comment trouver le complément à 2 d'un entier négatif.

\begin{Exemple}
on souhaite trouver le complément à 2 de $\base{-113}{10}$ sur une mémoire de 8 bits.
\begin{itemize}
\item Le complément à 2 de $\base{113}{10}$ est $\base{01110001}{2}$.
\item Le complément à 1 de $\base{01110001}{2}$ est $\base{10001110}{2}$ (on change tous les 0 en 1 et tous les 1 en 0).
\item On ajoute 1 au binaire obtenu : $\base{10001111}{2}$.
\end{itemize}
Le complément à 2 de $\base{-113}{10}$ est donc $\base{10001111}{2}$.
\end{Exemple}

\subsubsection{Soustraction}

Calculer $a-b$ revient à calculer $a+(-b)$. 

Ainsi, effectuer une soustraction revient à faire une addition.

\newpage

\subsection{En Python}

Quand on souhaite qu'une variable soit entière, on utilise la syntaxe suivante :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&int(3/2)
\end{tabularx}

\Par

Ici, la console affiche l'entier correspondant au résultat de la division de 3 par 2 (à savoir 1).

\Par

Si on tape :

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&a = -3\\
&type(a)
\end{tabularx}

\Par

on voit s'afficher :
\begin{center}
\texttt{<class 'int'>}.
\end{center}

Cela signifie que la variable \texttt{a} est considérée comme un entier.\enlargethispage*{2em}

\begin{solintro}
\begin{questions}
\item Donner le complément à 2 du nombre 78 est le binaire signé correspondant car il est positif.
\[
78 = 64 + 8 + 4 + 2 = 2^6+2^3+2^2+2.
\]
On en déduit que $\base{78}{10}=\base{01001110}{2}$.


\item $111=64+32+8+4+2+1=2^6 + 2^5 + 2^3 + 2^2 + 2^1 + 2^0$ donc :
\[
\base{111}{10}=\base{01101111}{2}.
\]
Le complément à 1 de ce binaire est donc : $\base{10010000}{2}$.

En ajoutant 1, on trouve : $\base{10010001}{2}$.

Le complément à 2 de $\base{-111}{10}$ est donc $\base{10010001}{2}$.

\item Ajoutons les compléments à 2 des nombres 78 et $-111$ :

\[
\begin{array}{*{11}{c}}
 & &0&1&0&0&1&1&1&0\\
+& &1&0&0&1&0&0&0&1\\
\hline
&&1&1&0&1&1&1&1&1
\end{array}
\]
Le complément à 2 de la somme $78+(-111)$ est donc $\base{11011111}{2}$.

\item $78+(-111)=-33$. Or, $33=32+1=2^6+2^0$.

Le binaire signé de $\base{33}{10}$ est donc $\base{00100001}{2}$.

Le complément à 1 de ce binaire est : $\base{11011110}{2}$.

Le complément à 2 de ce binaire est alors : $\base{11011111}{2}$.

On obtient bien le même binaire que dans la question précédente.
\end{questions}
\vspace*{-0.5em}
\end{solintro}


\section{Représentation approximative des nombres réels}

\begin{exointro}{\null}
\begin{questions}
\item Donner la représentation binaire de la fraction $\dfrac{11}{16}$.
\item Donner la représentation binaire de la fraction $\dfrac{11}{15}$.
\item Donner le début du développement dyadique de la somme $\dfrac{11}{16}+\dfrac{11}{15}$.

Le nombre affiché par un ordinateur sera-t-il représentatif de cette somme ?
\end{questions}
\end{exointro}

\subsection{Nombres décimaux (rappel)}

Un nombre décimal est un nombre s'écrivant sous la forme $\dfrac{x}{10^n}$, où $x$ est un entier relatif.

Posons :
\[
x=\pm\;\overline{a_pa_{p-1}\ldots a_1a_0}^{\;10}.
\]
Alors, 
\[
\dfrac{x}{10^n}=\pm\;\overline{a_pa_{p-1}\ldots a_n,a_{n-1}\ldots a_0a_1}^{\;10}.
\]
\begin{Exemple}
$\dfrac{13}{4}=\dfrac{325}{100}=\dfrac{325}{10^2}= 3,25$.
\end{Exemple} 

\subsection{Nombres dyadiques}

\begin{defin}
Par analogie avec les nombres décimaux, on appelle \textit{nombres dyadiques} les nombres qui s'écrivent sous la forme $\dfrac{x}{2^n}$, où $x\in\Z$ et $n\in\N$.
\end{defin}

\begin{Exemple}
$\dfrac{13}{4}=\dfrac{13}{2^2}$ est un nombre dyadique.
\end{Exemple}

\newpage

Pour obtenir le \textit{développement dyadique} d'un nombre dyadique $\dfrac{x}{2^n}$, on prend le binaire correspondant à $x$ et on insère une virgule avant le $n$-ième bit en partant de la fin.

\begin{Exemple}
$\base{13}{10}=\base{1101}{2}$.

Le développement dyadique de $\dfrac{13}{2^2}$ est donc $\base{11,01}{2}$.
\end{Exemple}

Cela signifie que :

\Par

\[
\dfrac{13}{4}=1\times2^1 + 1\times2^0 + 0\times\dfrac{1}{2^1} + 1\times\dfrac{1}{2^2}.
\]

\Par

Il existe des nombres décimaux qui ne sont pas dyadiques, et par conséquent, qui n'admette pas de développement dyadique fini. 

\begin{Exemple}
$\base{0,1}{10}=\base{0,000110011001100110011001100110011001100110011\ldots}{2}$.
\end{Exemple}

Par conséquent, leur représentation machine sera nécessairement tronquée, et cela engendrera des erreurs dans les opérations.

Sous Python par exemple, quand on tape :

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&0.1+0.2
\end{tabularx}

la console nous retourne :
\begin{center}
\texttt{0.30000000000000004}
\end{center}

\Par

%\begin{aretenir}Un calcul sur des nombres décimaux peut comporter des erreurs\linebreak d'approximation. C'est le cas quand l'un des deux nombres n'a pas un développement dyadique fini.\end{aretenir}

\begin{anecdote}
Le 25 février 1991, à Dharan en Arabie Saoudite, un missile Patriot américain a raté l'interception d'un missile Zcud irakien, ce dernier provoquant la mort de 28 personnes. La commission d'enquête chargée d'expliquer la raison de cet échec a mis en évidence le défaut suivant : l'horloge interne du missile Patriot mesure le temps en dixième de seconde. Pour obtenir le temps en seconde, le système
multiplie ce nombre par 10 en utilisant un registre de 24 bits en virgule fixe. Or 1/10 n'est pas un nombre dyadique à développement fini donc a été arrondi : le registre de 24 bits contient $\base{0,00011001100110011001100}{2}$ et induit une erreur binaire de $\base{0,0000000000000000000000011001100\ldots}{2}$, soit approximativement $\base{\numprint{0,000000095}}{10}$.

En multipliant cette quantité par le nombre de dixièmes de seconde pendant 100 heurs (le temps écoulé entre la mise en marche du système et le lancement du missile Patriot), on obtient le décalage entre l'horloge interne de missile et le
temps réel, soit :
\[
\numprint{0,000000095}\times 100 \times \numprint{3600}\times 10 \approx 0,34~\text{s}.
\]
\vspace*{-1.5em}
\Break
Or un missile Zcud vole à la vitesse approximative de 1,676 m/s donc parcourt plus de 500 m en 0,34 s, ce qui le fait largement sortir de la zone d'acquisition de sa cible par le missile d'interception.

\Par

\begin{flushright}
Source : http://ta.twi.tudelft.nl/nw/users/vuik/wi211/disasters.html.
\end{flushright}
\end{anecdote}

\subsection{Norme IEEE-754 (complément d'information)}

Tout comme il existe une écriture scientifique pour les nombres décimaux, écriture sous la forme $a\times10^n$ où $1\leqslant a <10$ et $n\in\Z$, il existe une écriture équivalente en binaire, écriture de la forme $\overline{1,b_1b_2\cdots b_k}^{\;2}$.

Par exemple, $\dfrac{13}{4}=3,25=\base{11,01}{2}=\base{1,101}{2}\times2^1$.

\Par

La suite de bits $b_1b_2\ldots b_k$ est appelée la \textit{mantisse} du nombre, et l'exposant de 2 est tout simplement appelé l'\textit{exposant}.

Sur 64 bits, un nombre dyadique sera codé de telle façon que :
\begin{itemize}
\item le bit fort représente son signe;
\item les 11 bits suivants représentent l'exposant;
\item les 52 autres bits représentent la mantisse.
\end{itemize}

Nous n'irons pas plus loin car ce paragraphe est hors-programme.

\subsection{Nombres réels}

De façon analogue aux nombres décimaux, un nombre réel $x$ sera codé en binaire à l'aide de son écriture décimale.

Voyons la méthode à travers un exemple.

\begin{methode}
On pose $x=\dfrac{1}{3}\approx0,333333\ldots$.

\begin{itemize}
\item $0,333333\ldots \times2 = \boxed{0},666666\ldots$
\item $0,666666\ldots \times2 = \boxed{1},333333\ldots$
\item On ne prend que la partie décimale du résultat précédent :\\ $0,333333\ldots \times2 = \boxed{0},666666\ldots$
\item etc.
\end{itemize}

Ainsi, la représentation binaire du nombre $\dfrac{1}{3}$ est $\base{0,010101\ldots}{2}$.
\end{methode}

\subsection{Flottants, Python et tests d'égalité}

En Python, quand on tape :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&type(1/3)
\end{tabularx} 

\Par

la console nous renvoie :

\begin{center}
\texttt{<class 'float'>}
\end{center}

En effet, dans un cas général, en informatique, les nombres à virgule sont appelés  des \textit{nombres flottants} ou \textit{nombres à virgule flottante}.

\Par

Pour les raisons d'approximations que nous avons vues précédemment, il faudra éviter les tests d'égalité entre deux flottants.

En effet, en Python, quand on tape :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&0.1+0.2 == 0.3
\end{tabularx}

\Par

la console renvoie :
\begin{center}
\texttt{False}
\end{center}

ce qui signifie que pour Python, la représentation binaire du résultat de $0,1+0,2$ n'est pas identique à celle du nombre 0,3.

\enlargethispage*{2em}

\begin{aretenir}\label{dev-dyadique-de-1}
En Python, le développement dyadique $\base{0,111111\ldots}{2}$ correspond au nombre 1 (cela a un rapport avec la norme IEEE-754 mais nos connaissances actuelles ne nous permettent pas encore de comprendre la raison pour laquelle on a ce résultat).
\end{aretenir}


\begin{solintro}
\begin{questions}
\item $\dfrac{11}{16}$ est un nombre dyadique et :
\[
\dfrac{11}{16}=\dfrac{8+2+1}{16}=\dfrac{8}{16}+\dfrac{2}{16}+\dfrac{1}{16}=\dfrac{1}{2}+\dfrac{1}{8}+\dfrac{1}{16}.
\]
Donc $\dfrac{11}{16}=\base{0,1011}{2}$.

\item $\dfrac{11}{15}$ n'est pas un nombre dyadique car son dénominateur n'est pas une puissance de 2.

\[ 
\dfrac{11}{15}\approx0,7333\ldots
\]
\BreakWithoutItem
\begin{itemize}
\item $0,7333\ldots \times 2 =\boxed{1},4666\ldots$
\item $0,4666\ldots\times2=\boxed{0},9333\ldots$
\item $0,9333\ldots\times2=\boxed{1},8666\ldots$
\item $0,8666\ldots\times2=\boxed{1},7333\ldots \leftarrow $ on est revenu au point de départ.
\end{itemize}

Donc $\dfrac{11}{15}=\base{0,\underline{1011}10111011\ldots}{2}$.

\begin{Remarque}
nous avons souligné la période du binaire, c'est-à-dire la partie qui se répète indéfiniment.
\end{Remarque}

\item Le binaire de la somme $\dfrac{11}{16}+\dfrac{11}{15}$ est :
\[
\begin{array}{*{12}{c}}
  & 0 & , & 1 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & \ldots\\
+ & 0 & , & 1 & 0 & 1 & 1 & 1 & 0 & 1 & 1 & \ldots\\
\hline
 & 1 &  , &  0 & 1  & 1  & 0 &  1 & 0  &  1 & 1  & \ldots
\end{array}
\]
Ce binaire correspond au nombre :

\[
1 \times 2^0 + 0 \times\dfrac{1}{2^1} + 1\times\dfrac{1}{2^2} + 1\times\dfrac{1}{2^3} + 0 \times \dfrac{1}{2^4} + 1\times\dfrac{1}{2^5} +  \cdots
\]

Le résultat en base 10 affiché ne sera pas la valeur exacte de la somme $\dfrac{11}{16}+\dfrac{11}{15}$ car l'un des deux nombres n'est pas dyadique et son développement dyadique n'est pas fini.
\end{questions}
\end{solintro}

\section{Les booléens}

\begin{exointro}{\null}
Si \texttt{a} et \texttt{b} sont deux booléens tels que \texttt{a=1} et \texttt{b=0}, que vaut le booléen :
\begin{center}
\texttt{not(a or b) or (a and not(b))} ?
\end{center}
\end{exointro}

\subsection{Définition}

\begin{defin}
Un \textit{booléen} est un type de variable à deux états, généralement nommés \textit{vrai} et \textit{faux}, et représentés respectivement par 1 et 0.
\end{defin}

En Python, on peut déclarer un booléen directement par sa valeur : \og True \fg{} (pour \textit{vrai}) et \og False \fg{} (pour \textit{faux}). Par exemple :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&couleur = True\\
&nb = False
\end{tabularx}

\subsection{Opérateur de comparaison}

Un booléen peut être le résultat d'un test. Par exemple :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&a = 10\\
&print(a > 4)
\end{tabularx}

\Par

Le résultat affiché est alors : \texttt{True} car \texttt{a} est effectivement strictement supérieur à 4, puisqu'il vaut 10.

Les différents opérateurs de comparaison possibles sont les suivants :

\Par

\begin{center}
\begin{tabular}{|Zc|Zc|}
\hline
\tabulartitle
Opérateur & Signification\\
\hline
< & strictement inférieur\\
\hline
<= & inférieur ou égal\\
\hline
> & strictement supérieur\\
\hline
>= & supérieur ou égal\\
\hline
== & égal\\
\hline
!= & différent\\
\hline
\end{tabular}
\end{center}

\Par

\begin{attention}
Quand on veut tester une égalité, il faut faire attention à mettre \mbox{deux signes \og = \fg} à la suite :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&a = 2048\\
&b = 2**11\\
&print(a == b)
\end{tabularx}

\Par

Ce programme affiche \og True \fg{} car $\numprint{2048}=2^{11}$.
\end{attention}

\newpage

\subsection{Opérateurs booléens}

\subsubsection{L'opérateur \og and \fg}

L'opérateur \og and \fg{} permet de tester si deux booléens sont vrais.

On a alors la table suivante :

\Par

\begin{center}
\begin{tabular}{|C|Zc|Zc|}
\hline
\tabulartitle
and & 0 & 1\\
\hline
0 & 0 & 0\\
\hline
1 & 0 & 1\\
\hline
\end{tabular}
\end{center}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&note = 13.5\\
&mention\verb+_+ab = note >=12 and note < 14\\
&print(mention\verb+_+ab)
\end{tabularx}

\Par

Le booléen \texttt{mention}\verb+_+\texttt{ab} est le résultat de : \texttt{note >= 12} (qui vaut \textit{True}) ET\linebreak \texttt{note < 14} (qui vaut \textit{True}).

D'après la table précédente, \texttt{mention}\verb+_+\texttt{ab = True}.
\end{Exemple}

\subsubsection{L'opérateur \og or \fg}

L'opérateur \og or \fg{} permet de tester si l'un des deux booléens au moins est vrai.

On a alors la table suivante :

\Par

\begin{center}
\begin{tabular}{|C|Zc|Zc|}
\hline
\tabulartitle
or & 0 & 1\\
\hline
0 & 0 & 1\\
\hline
1 & 1 & 1\\
\hline
\end{tabular}
\end{center}


\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&note = 16.5\\
&extreme = note < 5 or note > 15\\
&print(extreme)
\end{tabularx}

\Par

Ici, on teste si l'un ou l'autre des booléens \texttt{note < 5} et \texttt{note > 15} est vrai. C'est effectivement le cas donc le booléen \texttt{extreme} vaut \texttt{True}.
\end{Exemple}


\subsubsection{L'opérateur \og not \fg}

L'opérateur \og not \fg{} retourne le booléen opposé.

On a alors la table suivante :

\Par

\begin{center}
\begin{tabular}{|C|Zc|Zc|}
\hline
\tabulartitle
& 0 & 1\\
\hline
not & 1 & 0\\
\hline
\end{tabular}
\end{center}


\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&couleur = True\\
&nb = not couleur
\end{tabularx}

\Par

Ici, on définit le booléen \texttt{nb} comme étant le contraire du booléen \texttt{couleur}. Ainsi, \texttt{nb = False}.
\end{Exemple}

\subsubsection{L'opérateur \og xor \fg{} (ou exclusif)}

Cet opérateur retourne \og vrai \fg{} quand seulement l'un des deux booléens est vrai, et \og faux \fg{} sinon.

On a alors la table suivante :

\Par

\begin{center}
\begin{tabular}{|C|Zc|Zc|}
\hline
\tabulartitle
xor & 0 & 1\\
\hline
0 & 0 & 1\\
\hline
1 & 1 & 0\\
\hline
\end{tabular}
\end{center}


\subsubsection{En Python : le mot-clé \og in \fg}
\label{mot-cle-in}

Ce mot-clé permet de vérifier si une chaîne de caractères est contenue dans une autre.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&phrase = "Le dormeur du val est un poème d'Arthur Rimbaud"\\
&resultat = "val"\\
&print(resultat in phrase)
\end{tabularx}

\Par

Le programme affiche \og True \fg{} car la chaîne de caractères \og val \fg{} fait bien partie de la phrase.
\end{Exemple}

\begin{Remarque}
ce mot-clé est aussi utile pour des \textit{listes}, mais nous en parlerons dans le chapitre suivant, à la page \pageref{mot-cle-InPourListe}.
\end{Remarque}


\begin{solintro}
Prenons les choses petit à petit :
\begin{itemize}
\item \texttt{(a or b)} = (\texttt{1 or 0}) = 1; donc \texttt{not(a or b)} = \texttt{not(1)} = \texttt{0};
\item \texttt{not(b)} = \texttt{not(0)} = \texttt{1}, donc \texttt{a and not(b)} = \texttt{1 and 1} = \texttt{1};
\end{itemize}

On en déduit que \texttt{not(a or b) or (a and not(b))} = \texttt{0 or 1} = \texttt{1}.
\end{solintro}

\section{Les variables sous Python}

\begin{exointro}{\null}
\'Ecrire un programme Python :
\begin{questions}
\item qui demande à l'utilisateur.trice. de saisir une phrase;
\item qui convertit la saisie en minuscules;
\item qui détecte si la chaîne \og ui \fg{} apparaît dans la saisie;
\item qui affiche la longueur de la saisie;
\item qui affiche les 5 derniers caractères si la saisie est strictement plus longue que 5 caractères;
\item qui remplace tous les \og e \fg{} en \og * \fg{} et qui affiche le résultat.
\end{questions}
\end{exointro}

\subsection{Les variables numériques}

En Python, il n'est pas nécessaire de se préoccuper du type des variables\linebreak numériques.

En effet, Python s'adapte automatiquement. Par exemple, le programme suivant conviendra parfaitement :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&a, b = 5, 3.8\\
&print(a+b)
\end{tabularx}

\Par

La première ligne affecte la valeur \og 5 \fg{} à la variable \texttt{a} et la valeur \og 3,8 \fg{} à la variable \texttt{b}.

La seconde ligne calcule la somme des valeurs contenues dans les deux variables, et affiche donc : \og 8.8 \fg.

\Par

Rappelons ici les opérations de base sur les variables numériques.

\begin{itemize}
\item \texttt{a += 1} : ajoute 1 à la variable \texttt{a}.

On peut aussi écrire : \texttt{a = a+1}.

\item \texttt{a -= 1} : enlève 1 à la variable \texttt{a}.

On peut aussi écrire : \texttt{a = a-1}.

\item \texttt{a *= 2} : multiplie par 2 la variable \texttt{a}.

On peut aussi écrire : \texttt{a = a*2}.

\item \texttt{a /= n} : divise par \texttt{n} la variable \texttt{a}.

On peut aussi écrire : \texttt{a = a/n}.

\newpage

\item \texttt{a**n} : élève à l'exposant \texttt{n} la variable \texttt{a}.

Par exemple, \texttt{2**3} donne \og 8 \fg{} car $2^3=8$.

\item \texttt{a**0.5} : calcule la racine carrée de la variable \texttt{a}.

Par exemple, \texttt{9**0.5} donne \og 3 \fg{} car $\sqrt9=3$.

\item \texttt{a//b} : donne le quotient de la division euclidienne de \texttt{a} par \texttt{b}.

Par exemple, \og 87//42 \fg{} donne \og 2 \fg{} car $87=2\times42+3$.

\item \texttt{a\%b} : donne le reste de la division euclidienne de \texttt{a} par \texttt{b}.

Par exemple, \og 87\%42 \fg{} donne \og 3 \fg{} car $87=2\times42+3$.
\end{itemize}

\subsection{Les chaînes de caractères}

Sous Python, elle sont déclarées entre guillemets ou entre deux apostrophes, comme dans l'exemple suivant :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&prenom = "Kévin"\\
&surnom = 'kéké'
\end{tabularx}

\begin{attention}
En Python, il faut éviter de déclarer une chaîne de caractères avec des variables en majuscules.

Ainsi, \og MaVille \fg{} est à éviter; on préfèrera : \og ma\verb+_+ville \fg.

C'est plus une convention qu'une règle fondamentale; les variables \texttt{MaVille} et \texttt{ma}\verb+_+\texttt{ville} sont différentes : elles ne désignent pas la même chose. Ainsi, pour ne pas confondre les variables écrites avec ou sans majuscules, il est préférable de ne mettre aucune majuscule.
\end{attention}

\subsubsection{Concaténation}

\begin{defin}
La \textit{concaténation} de deux chaînes de caractères est le fait de les mettre l'une à la suite de l'autre.
\end{defin}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&a, b = "Ludovic", "Lulu"\\
&phrase = a + ", surnommé " + b + ", habite Bordeaux."\\
&print(phrase)
\end{tabularx}

\Par

Ce programme affiche : \og Ludovic, surnommé Lulu, habite Bordeaux. \fg{} 
\end{Exemple}

Si on veut écrire une centaine de fois une chaîne de caractères, on peut faire ainsi :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&lettre = "A"\\
&print(lettre*100)
\end{tabularx}

\subsubsection{Longueur d'une chaîne de caractères}
\label{fonction-len-chaine}

Dans de nombreux programmes, connaître la longueur d'une chaîne de caractères s'avère utile. Dans la plupart des langages de programmation, ce sera possible à l'aide de la fonction \texttt{len} (de l'anglais \og length \fg, signifiant \textit{longueur}).

\begin{Remarque}
on dit que \texttt{len} est une \textit{apocope} du mot anglais \og length \fg.
\end{Remarque}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&phrase = "Le dormeur du val ne se réveille pas."\\
&print(len(phrase))
\end{tabularx}

\Par

Ce programme affiche le nombre 37, nombre de caractères dans la chaîne \texttt{phrase}.
\end{Exemple}

\begin{Remarque}
cette fonction sert aussi à compter le nombre d'items dans une liste (nous en parlerons dans le chapitre suivant, page \pageref{fonction-len-liste}).
\end{Remarque}


\subsubsection{Partie de chaînes de caractères}

Si \texttt{chaine} est une chaîne de caractères alors :
\begin{itemize}
\item \texttt{chaine[0]} représente le premier caractère;
\item \texttt{chaine[1]} représente le deuxième caractère;
\item \texttt{chaine[2:7]} représente la partie de la chaîne comprise entre le troisième et le huitième caractère;
\item \texttt{chaine[-1]} représente le dernier caractère;
\item \texttt{chaine[-5:]} représente les cinq derniers caractères;
\item \texttt{chaine[5:]} représente la chaîne privée des 5 premiers caractères.
\end{itemize}

\begin{Exemple}
\texttt{phrase="Le dormeur du val ne se réveille pas."}.
\begin{itemize}
\item \texttt{phrase[0]} représente \og L \fg;
\item \texttt{phrase[1]} représente \og e \fg;
\item \texttt{phrase[3:9]} représente \og dormeur \fg;
\item \texttt{phrase[-1]} représente \og . \fg;
\item \texttt{phrase[-4:]} représente \og pas. \fg;
\item \texttt{phrase[3:]} représente \og dormeur du val ne se réveille pas. \fg.
\end{itemize}
\end{Exemple}

\newpage

\subsubsection{Le retour à la ligne}

Quand on concatène plusieurs chaînes de caractères et que l'on souhaite revenir à la ligne à chaque concaténation, on utilisera \og \textbackslash n \fg.

\Par

Par exemple, "Barbara\textbackslash nCassandre" donne :

\Par 

Barbara

Cassandre

\subsubsection{Caractère d'échappement}

Si une chaîne de caractères est définie entre deux apostrophes, et si elle contient elle-même une apostrophe, il est nécessaire d'\og échapper \fg{} cette dernière.

Par exemple, si la chaîne de caractères est \og Aujourd'hui \fg, on la définira ainsi :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
& chaine = 'Aujourd\textbackslash 'hui'
\end{tabularx}

\Par

Mais pour éviter ce cas de figure, on peut aussi définir la chaîne de caractères à l'aide de guillemets :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&chaine = "Aujourd'hui"
\end{tabularx}

\subsubsection{Majuscules et minuscules}

Python est sensible à la casse d'une chaîne de caractères : cela signifie qu'il\linebreak distingue les majuscules et les minuscules.

Ainsi, la chaîne \og Bordeaux \fg{} est différente de la chaîne \og bordeaux \fg. Il sera donc parfois utile de transformer une chaîne de caractères afin qu'elle ne contienne que des minuscules. On utilisera pour cela la méthode \texttt{lower}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&ville = input("Où habitez-vous ?")\\
&if (ville.lower() != "bordeaux"):\\
&\hspace*{2em}print("Vous ne connaissez sans doute pas la place Pey-Berland !")
\end{tabularx}

\Par

Dans ce programme, il est plus simple de transformer en minuscules la réponse saisie au clavier afin de la comparer à la chaîne de caractères \og bordeaux \fg; sans cela, il aurait fallu comparer toutes les écritures possibles de la ville (tout en\linebreak majuscules, tout en minuscules ou en minuscule à part l'initiale, etc.).
\end{Exemple}

Si on souhaite au contraire transformer la chaîne de caractères en majuscules, on utilisera la méthode \texttt{upper}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&ville = input("Où habitez-vous ?")\\
&if (ville.upper() != "BORDEAUX"):\\
&\hspace*{2em}print("Vous ne connaissez sans doute pas la place Pey-Berland !")
\end{tabularx}
\end{Exemple}

\begin{Remarque}
les caractères accentués sont aussi mis en majuscules. Par conséquent, la chaîne \og Stéphane \fg{} sera transformée en \og ST\'EPHANE \fg{} et non en\linebreak\og STEPHANE \fg.
\end{Remarque}

\subsubsection{Remplacer un caractère par un autre}

La méthode \texttt{replace(a,b)} permet de remplacer toutes les occurrences de \texttt{a}\linebreak par \texttt{b}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&chaine = "Levez-vous vite, orages désirés."\\
&chaine.replace('e','Z')
\end{tabularx}

\Par

Python renvoie :
\begin{center}
\texttt{'LZvZz-vous vitZ, oragZs désirés.'}
\end{center}
\end{Exemple}

\subsection{Changer le type d'une variable}

\subsubsection{Connaître le type d'une variable}

Si l'on ne sait pas comment est interprétée une variable par Python, on peut lui demander d'afficher son type comme ceci :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&chiffre = "3"\\
&print(type(chiffre))
\end{tabularx}

\Par

s'affichera alors : \og \texttt{<class 'str'>} \fg, ce qui signifie que la variable est de type \og string \fg, c'est-à-dire \og caractère \fg.

En revanche, si l'on tape :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&chiffre = 3\\
&print(type(chiffre))
\end{tabularx}

\Par

s'affichera la réponse : \og \texttt{<class 'int'>} \fg, qui signifie \og integer \fg, soit \og entier \fg.


Et si on tape :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&n = 3.7\\
&print(type(n))
\end{tabularx}

\Par


on verra s'afficher la réponse : \og \texttt{<class 'float'>} \fg, pour \og flottant \fg.

\subsubsection{Changer le type d'une variable}

Il sera parfois utile de transformer une variable de type caractère en une variable de type nombre, ne serait-ce que pour effectuer des calculs numériques, et inversement.

On peut alors faire comme dans l'exemple suivant :

\Par


\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&chiffre, nombre = "3", 3.7\\
&chiffre = int(chiffre)\\
&print(chiffre+nombre)
\end{tabularx}

\Par

Ici, nous admettons que nous partons d'une variable \texttt{chiffre} de type caractère et nous souhaitons effectuer la somme des variables \texttt{chiffre} et \texttt{nombre}. Sans transformer le type de la variable \texttt{chiffre}, cette opération mène à une erreur. 

En tapant \og \texttt{chiffre=int(chiffre)} \fg, on transforme le type \og caractère \fg{} en type \og entier \fg, et l'addition peut alors s'effectuer.

\Par

Pour transformer une variable entière en caractères, on procède de la même\linebreak manière :

\Par

\begin{tabularx}{\linewidth}{p{0.5cm}>{\ttfamily}X}
&chiffre, nombre = "3", 3.7\\
&nombre = str(nombre)\\
&print(chiffre+nombre)
\end{tabularx}

\Par

La réponse affichera : \og 33.7 \fg{} car les variables \texttt{chiffre} et \texttt{nombre} sont interprétées comme des chaînes de caractères; ainsi, l'instruction \og \texttt{chiffre}+\texttt{nombre} \fg{} concatène les deux variables et l'instruction \og print \fg{} affiche cette concaténation.\enlargethispage*{3em}

\begin{solintro}
\begin{listing}{}{02-solintro.py}\end{listing}
\end{solintro}