Résumé
Une expression arithmétique ne se calcule pas de gauche à droite comme on la lit, mais selon une structure cachée, son arbre, que fixent la priorité des opérateurs, leur associativité et les parenthèses ; et en chaque nœud de cet arbre, le type des opérandes décide quelle opération est effectuée, de sorte que 7 / 2 vaut 3 et 7 / 2.0 vaut 3.5. Cette leçon étudie les cinq opérateurs arithmétiques de C++ avec des entiers et avec des réels ; la division entière et le reste, qui depuis C++11 tronquent vers zéro, d’où il suit que le reste prend le signe du dividende et diffère du reste de la division euclidienne lorsque le dividende est strictement négatif ; la manière d’obtenir le reste euclidien ; l’arbre d’une expression ; le type du résultat lorsque les opérandes sont de types différents, et les deux manières dont une expression arithmétique entière perd son sens : diviser par zéro et déborder dans un calcul intermédiaire.
Objectifs d’apprentissage
- Calculer le quotient et le reste de la division entière en C++, y compris avec des opérandes négatifs, et les relier au quotient et au reste de la division euclidienne.
- Dessiner l’arbre d’une expression arithmétique selon la priorité et l’associativité, et calculer sa valeur.
- Prévoir le type du résultat d’une opération entre opérandes de types différents.
- Utiliser la division entière et le reste pour décomposer des quantités : les chiffres d’un nombre, une durée en heures et minutes, un jour de la semaine.
Les opérateurs arithmétiques
C++ possède cinq opérateurs arithmétiques binaires : l’addition +, la soustraction -, la multiplication *, la division / et le reste % ; il possède en outre le moins unaire, qui change le signe de son unique opérande, comme dans -x, et un plus unaire, +x, qui le laisse tel quel. Les quatre premiers s’appliquent aux entiers et aux réels ; le reste, aux entiers seulement. Or la même écriture ne désigne pas la même opération dans tous les cas : si les deux opérandes de / sont entiers, la division est entière et son résultat est un entier, le quotient privé de sa partie fractionnaire ; si l’un d’eux est réel, la division est réelle. La leçon Caractères, booléens, conversions et constantes a montré la conséquence la plus visible de cette règle, à savoir que double r{7 / 2}; stocke 3 : la division a été faite entre entiers avant que le résultat ne soit converti en réel.
Le programme applique les cinq opérateurs à 17 et 5, et répète la division avec un dividende réel.
#include <print>int main(){ const int a{17}; const int b{5}; std::println("{} + {} = {}", a, b, a + b); std::println("{} - {} = {}", a, b, a - b); std::println("{} * {} = {}", a, b, a * b); std::println("{} / {} = {}", a, b, a / b); std::println("{} % {} = {}", a, b, a % b); const double x{17.0}; std::println("{} / {} = {}", x, b, x / b);}17 + 5 = 2217 - 5 = 1217 * 5 = 8517 / 5 = 317 % 5 = 217 / 5 = 3.417 divisé par 5 donne 3 et il reste 2 : ce sont le quotient et le reste de la répartition de 17 objets en groupes de 5. La dernière ligne divise un réel par un entier et obtient 3.4. Il faut remarquer que std::println écrit le réel 17.0 sous la forme « 17 » : le marqueur vide écrit la représentation la plus courte de la valeur, de sorte que ce qui est écrit ne révèle pas le type ; pour le voir, on demande des décimales avec {:.1f}.
L’opérateur % n’admet pas les réels. Écrire 7.5 % 2 n’est pas une erreur de logique que le programme découvrirait à l’exécution, mais une erreur de compilation : le compilateur dit que les opérandes de types double et int ne sont pas valides pour l’opérateur.
#include <print>int main(){ std::println("{}", 7.5 % 2);}main.cpp: In function ‘int main()’:main.cpp:5:28: error: invalid operands of types ‘double’ and ‘int’ to binary ‘operator%’ 5 | std::println("{}", 7.5 % 2); | ~~~ ^ ~Le reste d’une division réelle existe, et c’est la fonction std::fmod de l’en-tête <cmath> qui le calcule ; elle sera étudiée dans la leçon Bits et bibliothèque mathématique, avec la puissance : C++ n’a pas d’opérateur de puissance, et 2 ^ 3 ne vaut pas 8, mais autre chose, qui sera expliqué là-bas.
Chargement du contenu…