Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
logique_et_calcul_booleen [2015/07/20 12:30] 77.148.2.219 [Les opérateurs logiques] |
logique_et_calcul_booleen [2016/07/25 18:04] (Version actuelle) gbdivers |
||
---|---|---|---|
Ligne 4: | Ligne 4: | ||
====== Logique binaire et calcul booléen ====== | ====== Logique binaire et calcul booléen ====== | ||
- | La représentation en base 2, le binaire, possède une importance particulière en informatique. Vous avez vu dans les chapitres précédents que vous pouvez représenter les nombres entier sous forme binaire (une suite de 0 et de 1) en utilisant le préfixe ''0b''. Vous pouvez également écrire des valeurs booléennes en utilisant les mots-clés ''true'' (vrai) et ''false'' (faux). | + | La représentation en base 2, le binaire, possède une importance particulière en informatique. Vous avez vu dans les chapitres précédents que vous pouvez représenter les nombres entiers sous forme binaire (une suite de 0 et de 1) en utilisant le préfixe ''0b''. Vous pouvez également écrire des valeurs booléennes en utilisant les mots-clés ''true'' (vrai) et ''false'' (faux). |
Cette forme de logique est tellement importante qu'un chapitre complet lui est consacré (et vous reviendrez plusieurs fois sur ces notions durant le cours). | Cette forme de logique est tellement importante qu'un chapitre complet lui est consacré (et vous reviendrez plusieurs fois sur ces notions durant le cours). | ||
Ligne 10: | Ligne 10: | ||
En électronique, il est facile de représenter des valeurs binaires en utilisant des tensions différentes. Par exemple, on va définir que l'état "vrai" sera représenté par une tension de +5V et l'état "faux" par une tension de 0V. (En pratique, les valeurs prises seront très variables selon les composants de l'ordinateur, mais le principe reste le même.) | En électronique, il est facile de représenter des valeurs binaires en utilisant des tensions différentes. Par exemple, on va définir que l'état "vrai" sera représenté par une tension de +5V et l'état "faux" par une tension de 0V. (En pratique, les valeurs prises seront très variables selon les composants de l'ordinateur, mais le principe reste le même.) | ||
- | Ces valeurs binaires utilisées en interne sont appelées "bits" et correspondent au plus petit élément d'information que peut manipuler un ordinateur. Tous les autres type de données (aussi bien les nombres que les chaînes de caractères) sont définis à partir d'une représentation interne en bits. Même les nombres binaires et les booléens que vous utiliser en C++ sont représentés par des bits dans l'ordinateur. | + | Ces valeurs binaires utilisées en interne sont appelées "bits" et correspondent au plus petit élément d'information que peut manipuler un ordinateur. Tous les autres types de données (aussi bien les nombres que les chaînes de caractères) sont définis à partir d'une représentation interne en bits. Même les nombres binaires et les booléens que vous utilisez en C++ sont représentés par des bits dans l'ordinateur. |
Il est possible en C++ de manipuler directement les représentations internes des valeurs, mais cela est beaucoup plus complexe et moins sécurisé que de manipuler les types du C++. Vous n'aurez besoin de faire cela que dans des cas très spécifiques (programmation de micro-contrôleur, optimisation bas niveau), mais vous verrez comment faire cela. | Il est possible en C++ de manipuler directement les représentations internes des valeurs, mais cela est beaucoup plus complexe et moins sécurisé que de manipuler les types du C++. Vous n'aurez besoin de faire cela que dans des cas très spécifiques (programmation de micro-contrôleur, optimisation bas niveau), mais vous verrez comment faire cela. | ||
- | La notation des valeurs binaires "vrai" et "faux" est purement arbitraire. Vous pouvez définir que les valeurs binaires sont "haut" et "bas", "droite" et "gauche" ou n'importe quoi d'autre. Le plus important est que cela représente deux états différents. Dans du code C++, vous avez deux manière de représenter les valeurs binaires : | + | La notation des valeurs binaires "vrai" et "faux" est purement arbitraire. Vous pouvez définir que les valeurs binaires sont "haut" et "bas", "droite" et "gauche" ou n'importe quoi d'autre. Le plus important est que cela représente deux états différents. Dans du code C++, vous avez deux manières de représenter les valeurs binaires : |
* avec 0 et 1, pour représenter un nombre entier ; | * avec 0 et 1, pour représenter un nombre entier ; | ||
Ligne 50: | Ligne 50: | ||
==== Les opérateurs logiques ==== | ==== Les opérateurs logiques ==== | ||
- | Les booléens ne se manipulent pas comme des nombres entiers. En effet, cela n'a pas de sens de faire des opérations arithmétiques dessus. Les booléens permettent un nombre limité d'opérations logiques, qui prennent un ou deux booléens et retourne un nouveau booléen. | + | Les booléens ne se manipulent pas comme des nombres entiers. En effet, cela n'a pas de sens de faire des opérations arithmétiques dessus. Les booléens permettent un nombre limité d'opérations logiques, qui prennent un ou deux booléens et retournent un nouveau booléen. |
- | <note info>Faire des opérations arithmétiques sur les booléens ne provoquera pas d'erreur de compilation, vous pouvez donc écrire par exemple ''true + 2''. La raison est que les valeurs booléennes sont représentée en interne par des nombres (généralement 0 et 1) et que cela a un sens, **pour l'ordinateur**, de faire ce type d'opération. | + | <note info>Faire des opérations arithmétiques sur les booléens ne provoquera pas d'erreur de compilation, vous pouvez donc écrire par exemple ''true + 2''. La raison est que les valeurs booléennes sont représentées en interne par des nombres (généralement 0 et 1) et que cela a un sens, **pour l'ordinateur**, de faire ce type d'opération. |
Mais cela n'a pas de sens en termes de logique (quel sens pourrait-on donner à l'expression ''true + 2'' ?). | Mais cela n'a pas de sens en termes de logique (quel sens pourrait-on donner à l'expression ''true + 2'' ?). | ||
Ligne 101: | Ligne 101: | ||
</code> | </code> | ||
- | La dernière opérateur est la disjonction ''||'', qui prend également deux booléens et retourne vrai si au moins un des deux booléens est vrai. Cette opération est également appelée "OR" ou "OU", puisque pour que le résultat soit vrai, il faut que le premier booléen soit vrai OU que le second booléen soit vrai. | + | La dernière opération est la disjonction ''||'', qui prend également deux booléens et retourne vrai si au moins un des deux booléens est vrai. Cette opération est également appelée "OR" ou "OU", puisque pour que le résultat soit vrai, il faut que le premier booléen soit vrai OU que le second booléen soit vrai. |
Ligne 129: | Ligne 129: | ||
La seconde version de la disjonction est le "OU exclusif" ou "XOR". Dans ce cas, il faut prendre le "OU" au sens strict : "le premier booléen est vrai OU le second booléen est vrai, mais pas les deux en même temps". | La seconde version de la disjonction est le "OU exclusif" ou "XOR". Dans ce cas, il faut prendre le "OU" au sens strict : "le premier booléen est vrai OU le second booléen est vrai, mais pas les deux en même temps". | ||
- | Il n'existe pas en C++ d'opérateur "Ou exclusif", mais il est possible de le simuler avec les autres opérateurs.</note> | + | Il n'existe pas en C++ d'opérateur logique "Ou exclusif", mais il est possible de le simuler avec les autres opérateurs.</note> |
- | Ces opérateurs peuvent être résumé dans un tableau (appelé table de vérité) : | + | Ces opérateurs peuvent être résumés dans un tableau (appelé table de vérité) : |
^ ''a'' ^ ''b'' ^ ''!a'' ^ ''a && b'' ^ ''a || b'' ^ | ^ ''a'' ^ ''b'' ^ ''!a'' ^ ''a && b'' ^ ''a || b'' ^ | ||
Ligne 139: | Ligne 139: | ||
| 1 | 1 | 0 | 1 | 1 | | | 1 | 1 | 0 | 1 | 1 | | ||
- | Pour terminer, les opérateurs logiques du C++ fonctionne en utilisant l'évaluation paresseuse (//lazy evaluation//). Cela permet d'évaluer les opérandes uniquement si nécessaire. Imaginons les opérations suivantes, dans lesquelles "expression complexe" est un code quelconque qui prend du temps pour être évalué : | + | Pour terminer, les opérateurs logiques du C++ fonctionnent en utilisant l'évaluation paresseuse (//lazy evaluation//). Cela permet d'évaluer les opérandes uniquement si nécessaire. Imaginons les opérations suivantes, dans lesquelles "expression complexe" est un code quelconque qui prend du temps pour être évalué : |
<code> | <code> | ||
Ligne 146: | Ligne 146: | ||
</code> | </code> | ||
- | Avec le tableau précédent, on peut remarquer que si ''a'' est faux, alors le résultat de ''a && (expression complexe)'' sera toujours faux, quelque soit la valeur de ''expression complexe''. Dans ce cas, il n'est pas nécessaire d'évaluer "expression complexe", puisque sa valeur ne change pas le résultat. | + | Avec le tableau précédent, on peut remarquer que si ''a'' est faux, alors le résultat de ''a && (expression complexe)'' sera toujours faux, quelle que soit la valeur de ''expression complexe''. Dans ce cas, il n'est pas nécessaire d'évaluer "expression complexe", puisque sa valeur ne change pas le résultat. |
- | De la même façon, si ''b'' est vrai dans la seconde expression, le résultat de ''b || (expression complexe)'' sera toujours vrai quelque soit la valeur de ''expression complexe'', il n'est pas nécessaire d'évaluer ''expression complexe''. | + | De la même façon, si ''b'' est vrai dans la seconde expression, le résultat de ''b || (expression complexe)'' sera toujours vrai quelle que soit la valeur de ''expression complexe'', il n'est pas nécessaire d'évaluer ''expression complexe''. |
<note erreur>Cette technique permet de gagner en performances, en évitant de faire des calculs inutiles, mais cela implique une contrainte : il ne faut JAMAIS mettre dans une expression logique des calculs qui peuvent modifier le comportement du programme. Il sera plus sûr de séparer ces calculs et les opérations logiques dans le code.</note> | <note erreur>Cette technique permet de gagner en performances, en évitant de faire des calculs inutiles, mais cela implique une contrainte : il ne faut JAMAIS mettre dans une expression logique des calculs qui peuvent modifier le comportement du programme. Il sera plus sûr de séparer ces calculs et les opérations logiques dans le code.</note> | ||
Ligne 158: | Ligne 158: | ||
Une méthode classique pour écrire une expression retournant un booléen est d'utiliser les opérateurs de comparaison. Comme leur nom l'indique, ces opérateurs permettent de comparer des valeurs et de retourner vrai ou faux, selon le résultat de cette comparaison. Ces opérateurs sont les suivants : | Une méthode classique pour écrire une expression retournant un booléen est d'utiliser les opérateurs de comparaison. Comme leur nom l'indique, ces opérateurs permettent de comparer des valeurs et de retourner vrai ou faux, selon le résultat de cette comparaison. Ces opérateurs sont les suivants : | ||
- | * l'opérateur "EST ÉGAL" ''=='' permet de tester si deux valeurs sont égales ; | + | * l'opérateur "EST ÉGAL À" ''=='' permet de tester si deux valeurs sont égales ; |
- | * l'opérateur "EST DIFFÉRENT" ''!='' permet de tester si deux valeurs sont différentes ; | + | * l'opérateur "EST DIFFÉRENT DE" ''!='' permet de tester si deux valeurs sont différentes ; |
* l'opérateur "EST SUPÉRIEUR À" ''>'' permet de tester si la première valeur est supérieure à la seconde ; | * l'opérateur "EST SUPÉRIEUR À" ''>'' permet de tester si la première valeur est supérieure à la seconde ; | ||
* l'opérateur "EST SUPÉRIEUR OU ÉGAL À" ''>='' permet de tester si la première valeur est supérieure ou est égale à la seconde ; | * l'opérateur "EST SUPÉRIEUR OU ÉGAL À" ''>='' permet de tester si la première valeur est supérieure ou est égale à la seconde ; | ||
Ligne 194: | Ligne 194: | ||
Pour les nombres, ces opérateurs ne posent pas de difficultés particulières, leur fonctionnement correspond à ce que vous connaissez en mathématique. | Pour les nombres, ces opérateurs ne posent pas de difficultés particulières, leur fonctionnement correspond à ce que vous connaissez en mathématique. | ||
- | <note erreur>Les comparaison sur les chaînes de caractères est possible, mais nécessite quelques précautions. Vous verrez cela en détail dans __le chapitre sur les chaînes (lequel ?)__.</note> | + | <note erreur>Les comparaisons sur les chaînes de caractères sont possibles, mais nécessitent quelques précautions. Vous verrez cela en détail dans __le chapitre sur les chaînes (lequel ?)__.</note> |
- | Comme le langage C++ est permissif, la comparaison de valeurs de type différent ne produira pas forcément une erreur de compilation. Par exemple comparer un entier et un caractère : | + | Comme le langage C++ est permissif, la comparaison de valeurs de types différents ne produira pas forcément une erreur de compilation. Par exemple comparer un entier et un caractère : |
<code cpp> | <code cpp> | ||
Ligne 206: | Ligne 206: | ||
</code> | </code> | ||
- | Par contre, cela n'a pas de sens en termes de sémantique (comme on dit, on ne compte pas ensemble des pommes et des poires), il ne faut donc pas écrire ce type de code. En revanche, vous pouvez combiner le résultat de plusieurs comparaisons sur des valeurs de type différent en utilisant les opérateurs logiques : | + | Par contre, cela n'a pas de sens en termes de sémantique (comme on dit, on ne compte pas ensembles des pommes et des poires), il ne faut donc pas écrire ce type de code. En revanche, vous pouvez combiner le résultat de plusieurs comparaisons sur des valeurs de types différents en utilisant les opérateurs logiques : |
<code cpp> | <code cpp> | ||
Ligne 218: | Ligne 218: | ||
==== Exercices ==== | ==== Exercices ==== | ||
- | Evaluer le résultat de ces expressions (à la main, pas avec du code) : | + | * Evaluer le résultat de ces expressions (à la main, pas avec du code) : |
^ ''a'' ^ ''b'' ^ ''!a && b'' ^ ''!a || b'' ^ ''!a && !b'' ^ ''!a || !b'' ^ | ^ ''a'' ^ ''b'' ^ ''!a && b'' ^ ''!a || b'' ^ ''!a && !b'' ^ ''!a || !b'' ^ | ||
Ligne 226: | Ligne 226: | ||
| 1 | 1 | ? | ? | ? | ? | | | 1 | 1 | ? | ? | ? | ? | | ||
- | Quel combinaison des opérateurs logiques de base permettent d'obtenir un OU Exclusif ? Ecrivez le code C++ correspondant. | + | * Un OU Exclusif correspond à la table de vérité suivante. |
^ ''a'' ^ ''b'' ^ ''XOR'' ^ | ^ ''a'' ^ ''b'' ^ ''XOR'' ^ | ||
Ligne 233: | Ligne 233: | ||
| 1 | 0 | 1 | | | 1 | 0 | 1 | | ||
| 1 | 1 | 0 | | | 1 | 1 | 0 | | ||
+ | |||
+ | Dans le code suivant, replacer ''@@@@'' par une expression n'utilisant que les valeurs ''a'' et ''b'' et les opérateurs logiques ''&&'', ''||'' et ''!'', de façon à reproduire la table de vérité précédente. | ||
+ | |||
+ | |||
+ | <code cpp main.cpp> | ||
+ | #include <iostream> | ||
+ | |||
+ | bool eval(bool a,bool b) { | ||
+ | return (@@@@); | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | std::cout << std::noboolalpha; | ||
+ | std::cout << "| a | b | XOR " << std::endl; | ||
+ | std::cout << "| 0 | 0 | " << eval(false, false) << std::endl; | ||
+ | std::cout << "| 0 | 1 | " << eval(false, true) << std::endl; | ||
+ | std::cout << "| 1 | 0 | " << eval(true, false) << std::endl; | ||
+ | std::cout << "| 1 | 1 | " << eval(true, true) << std::endl; | ||
+ | } | ||
+ | </code> | ||
===== Représentation binaire des entiers ===== | ===== Représentation binaire des entiers ===== | ||
- | Comme vous l'avez vu dans les chapitres précédents, la façon dont vous écrivez un nombre dans le code et la façon dont il est affiché dans la console sont indépendant. Par défaut, l'écriture d'un nombre et son affichage se font en utilisant la base 10 (décimal), mais vous pouvez changer la base lors de l'écriture en utilisant un préfixe (''0b'', ''0'' et ''0x'') et lors de l'affichage en utilisant une directive (''std::oct'', ''std::dec'' et ''std::hex''). | + | Comme vous l'avez vu dans les chapitres précédents, la façon dont vous écrivez un nombre dans le code et la façon dont il est affiché dans la console sont indépendants. Par défaut, l'écriture d'un nombre et son affichage se font en utilisant la base 10 (décimal), mais vous pouvez changer la base lors de l'écriture en utilisant un préfixe (''0b'', ''0'' et ''0x'') et lors de l'affichage en utilisant une directive (''std::oct'', ''std::dec'' et ''std::hex''). |
<code cpp main.cpp> | <code cpp main.cpp> | ||
Ligne 255: | Ligne 275: | ||
</code> | </code> | ||
- | Il n'existe pas de directive pour afficher les nombres directement en binaire, on utilise souvent à la place la représentation hexadécimale. La raison est qu'il est relativement facile de faire la conversion entre hexadécimale et le binaire. En effet, un chiffre hexadécimal correspond exactement à quatre chiffres binaires, il faut donc utiliser la conversion suivante : | + | Il n'existe pas de directive pour afficher les nombres directement en binaire, on utilise souvent à la place la représentation hexadécimale. La raison est qu'il est relativement facile de faire la conversion entre hexadécimal et le binaire. En effet, un chiffre hexadécimal correspond exactement à quatre chiffres binaires, il faut donc utiliser la conversion suivante : |
^ hexadécimal ^ binaire ^ hexadécimal ^ binaire ^ | ^ hexadécimal ^ binaire ^ hexadécimal ^ binaire ^ | ||
Ligne 267: | Ligne 287: | ||
| 7 | 0111 | f | 1111 | | | 7 | 0111 | f | 1111 | | ||
- | Ainsi, pour convertir la valeur ''0x42'' en binaire, vous devez prendre le premier chiffre (''4''), le convertir en binaire (''0100''), puis faire la même chose avec le second chiffre (''2'', ce qui donne ''0010''). La représentation binaire finale est donc ''0b01000010''. | + | Ainsi, pour convertir la valeur ''0x2a'' en binaire, vous devez prendre le premier chiffre (''2''), le convertir en binaire (''0010''), puis faire la même chose avec le second "chiffre" (''a''), ce qui donne ''1010''). La représentation binaire finale est donc ''0b00101010''. |
<note>Il est quand même possible d'afficher la représentation binaire d'un nombre, en utilisant la classe ''std::bitset''. Cette classe sera étudiée en détail dans un chapitre Complément, mais pour le moment, vous pouvez utiliser la sytnaxe : | <note>Il est quand même possible d'afficher la représentation binaire d'un nombre, en utilisant la classe ''std::bitset''. Cette classe sera étudiée en détail dans un chapitre Complément, mais pour le moment, vous pouvez utiliser la sytnaxe : | ||
Ligne 290: | Ligne 310: | ||
Le chiffre 8 correspond au nombre de bits à utiliser, pensez à l'adapter si vous utilisez des nombres entiers plus grands. Et n'oubliez pas la directive d'inclusion ''bitset''.</note> | Le chiffre 8 correspond au nombre de bits à utiliser, pensez à l'adapter si vous utilisez des nombres entiers plus grands. Et n'oubliez pas la directive d'inclusion ''bitset''.</note> | ||
- | Comme cela a été expliqué au début du chapitre, toutes les valeurs que manipule un ordinateur sont en fait codée en interne en binaire. Cet encodage en binaire dans la mémoire de l'ordinateur est appelée //représentation binaire//. Vous n'aurez généralement pas besoin de manipuler directement les valeurs sous forme binaire, mais cette représentation est suffisamment importante pour que cela soit détaillé ici. | + | Comme cela a été expliqué au début du chapitre, toutes les valeurs que manipule un ordinateur sont en fait codées en interne en binaire. Cet encodage en binaire dans la mémoire de l'ordinateur est appelée //représentation binaire//. Vous n'aurez généralement pas besoin de manipuler directement les valeurs sous forme binaire, mais cette représentation est suffisamment importante pour que cela soit détaillé ici. |
La conversion des nombres entiers décimaux positifs en binaire est relativement simple. Pour les autres types de données (valeurs entières négatives, nombres réels, chaînes de caractères, etc.), la conversion n'est pas aussi simple et naturelle. Il existe en fait différentes normes de conversion, qui expliquent comment convertir une valeur d'un type donné en sa représentation binaire. Et il existe souvent plusieurs normes pour un même type de données. | La conversion des nombres entiers décimaux positifs en binaire est relativement simple. Pour les autres types de données (valeurs entières négatives, nombres réels, chaînes de caractères, etc.), la conversion n'est pas aussi simple et naturelle. Il existe en fait différentes normes de conversion, qui expliquent comment convertir une valeur d'un type donné en sa représentation binaire. Et il existe souvent plusieurs normes pour un même type de données. | ||
Ligne 304: | Ligne 324: | ||
<note>Vous rencontrerez souvent une notation un peu différente, utilisant les préfixes du système métrique : kilo-, méga-, giga- et téra-. Généralement, ces suffixes seront équivalents, c'est-à-dire seront basé sur un rapport de 1 à 1024 entre deux unités de grandeur. | <note>Vous rencontrerez souvent une notation un peu différente, utilisant les préfixes du système métrique : kilo-, méga-, giga- et téra-. Généralement, ces suffixes seront équivalents, c'est-à-dire seront basé sur un rapport de 1 à 1024 entre deux unités de grandeur. | ||
- | Cependant, dans le système métrique, le rapport devrait être de 1000 au lieu de 1024 et certains utilisent volontairement cette différence pour maintenir une ambiguïté chez le lecteur. Voir [[http://fr.wikipedia.org/wiki/Pr%C3%A9fixe_binaire|Préfixe binaire]] pour plus de détail.</note> | + | Cependant, avec le système métrique, le rapport devrait être de 1000 au lieu de 1024 et certains utilisent volontairement cette différence pour maintenir une ambiguïté chez le lecteur. Voir [[http://fr.wikipedia.org/wiki/Pr%C3%A9fixe_binaire|Préfixe binaire]] pour plus de détail.</note> |
==== Les opérateurs arithmétiques ==== | ==== Les opérateurs arithmétiques ==== | ||
Ligne 439: | Ligne 459: | ||
__ ajouter un schéma, comme pour les opérateurs suivants __ | __ ajouter un schéma, comme pour les opérateurs suivants __ | ||
- | Si on se rappelle que les 0 devant un nombre peuvent être ignorés (1 = 01 = 001 = 0001, etc.), on comprend que l'opération est réalisée sur des nombres entiers de 32 bits (ou 4 octets), quelque soit le nombre de bits que l'on utilise pour écrire le nombre. Les 0 manquant devant le nombre sont ajoutés avant l'opération. | + | Si on se rappelle que les 0 devant un nombre peuvent être ignorés (1 = 01 = 001 = 0001, etc.), on comprend que l'opération est réalisée sur des nombres entiers de 32 bits (ou 4 octets), quelque soit le nombre de bits que l'on utilise pour écrire le nombre. Les 0 manquants devant le nombre sont ajoutés avant l'opération. |
- | Cela signifie qu'en interne, ces nombres entiers sont représenté par défaut par 32 bits (4 octets), //quelque soit le nombre de bits utilisés pour les écrire//. | + | Cela signifie qu'en interne, ces nombres entiers sont représentés par défaut sur 32 bits (4 octets), //quelque soit le nombre de bits utilisés pour les écrire//. |
<note info>On pourrait penser que c'est du gâchis de mémoire d'utiliser 32 bits pour la représentation interne, alors que l'on écrit des nombres de 1 ou 6 bits. La raison est qu'un ordinateur est optimisé pour travailler avec des représentations de taille déterminée (généralement 32 ou 64 bits pour les ordinateurs de bureau). Le compilateur C++ adapte donc le nombre de bits en fonction de ce qui est le plus optimal pour l'ordinateur, mais il est possible de forcer l'utilisation de représentations de taille spécifique. Vous verrez cela dans un prochain chapitre.</note> | <note info>On pourrait penser que c'est du gâchis de mémoire d'utiliser 32 bits pour la représentation interne, alors que l'on écrit des nombres de 1 ou 6 bits. La raison est qu'un ordinateur est optimisé pour travailler avec des représentations de taille déterminée (généralement 32 ou 64 bits pour les ordinateurs de bureau). Le compilateur C++ adapte donc le nombre de bits en fonction de ce qui est le plus optimal pour l'ordinateur, mais il est possible de forcer l'utilisation de représentations de taille spécifique. Vous verrez cela dans un prochain chapitre.</note> | ||
Ligne 462: | Ligne 482: | ||
</code> | </code> | ||
- | <note warning>Remarquez bien les parenthèses. Sans celle-ci, le compilateur ne pourra pas faire la différence entre les opérateur de décalage de bits ''<<'' et ''>>'' et les opérateurs de flux ''<<'' et ''>>'', ce qui ne produira pas le comportement attendu. | + | <note warning>Remarquez bien les parenthèses. Sans celle-ci, le compilateur ne pourra pas faire la différence entre les opérateurs de décalage de bits ''<<'' et ''>>'' et les opérateurs de flux ''<<'' et ''>>'', ce qui ne produira pas le comportement attendu. |
- | Plus généralement, il faudra faire attention en C++ à la syntaxe, un même opérateur pouvant signifiant des choses différentes selon le contexte.</note> | + | Plus généralement, il faudra faire attention en C++ à la syntaxe, un même opérateur pouvant signifier des choses différentes selon le contexte.</note> |
affiche : | affiche : | ||
Ligne 503: | Ligne 523: | ||
==== Les opérateurs logiques bit à bit ==== | ==== Les opérateurs logiques bit à bit ==== | ||
- | Pour terminer, il existe les opérateurs logiques "AND" ("ET") ''&'', "OR" ("OU") ''|'' et XOR ("OU Exclusif") ''^'' pour les nombres. Ils sont similaire aux opérateurs de même nom que vous avez vu précédemment pour les booléens, sauf qu'ils s'appliquent sur chaque bit d'un nombre. Ainsi, le premier bit du résultat est calculé à partir du premier bit de chaque nombre, le deuxième bit du résultat à partir du deuxième bit de chaque nombre, et ainsi de suite. L'opérateur "OU exclusif" n'a pas d'équivalent pour les booléens, pour rappel il retourne vrai lorsque l'une des opérandes est vraie, mais pas les deux. | + | Pour terminer, il existe les opérateurs logiques "AND" ("ET") ''&'', "OR" ("OU") ''|'' et XOR ("OU Exclusif") ''^'' pour les nombres. Ils sont similaires aux opérateurs de même nom que vous avez vu précédemment pour les booléens, sauf qu'ils s'appliquent sur chaque bit d'un nombre. Ainsi, le premier bit du résultat est calculé à partir du premier bit de chaque nombre, le deuxième bit du résultat à partir du deuxième bit de chaque nombre, et ainsi de suite. L'opérateur "OU exclusif" n'a pas d'équivalent pour les booléens, pour rappel il retourne vrai lorsque l'une des opérandes est vraie, mais pas les deux. |
Par exemple, pour l'opérateur "AND", on aura le schéma suivant : | Par exemple, pour l'opérateur "AND", on aura le schéma suivant : | ||
Ligne 544: | Ligne 564: | ||
| 1 | 1 | 0 | 1 | 1 | 0 | | | 1 | 1 | 0 | 1 | 1 | 0 | | ||
- | ** Exos**: utilisation de mask avec opérateur logiques. | ||
- | |||
- | ===== Exercices ===== | ||
- | |||
- | Dans un ordinateur, composé de transistors, ces derniers forment des portes logiques. Ces portes permettent de réaliser tous les calculs. | ||
- | |||
- | * pour 1 bit, réécrire l'addition avec les opérations logiques | ||
- | * uniquement avec NAND | ||
- | * pour 8 bits, idem | ||
^ [[calculs_arithmetiques|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[nombres_reels|Chapitre suivant]] ^ | ^ [[calculs_arithmetiques|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[nombres_reels|Chapitre suivant]] ^ | ||
- | {{tag> Cours C++}} |