Les systèmes numériques
Dans cette page dédiée à l'étude des systèmes numériques avec le langage de programmation C#, nous allons de manière progressive et détaillée examiner comment il est possible de travailler avec des systèmes numériques variés et diversifiés, et également analyser avec précision la façon dont les nombres y sont organisés, représentés et manipulés selon des normes précises et universellement acceptées. Nous allons porter une attention particulière et concentrer nos efforts sur l'exploration approfondie des méthodes employées pour représenter les nombres à l'intérieur des systèmes numériques spécifiques comme les systèmes décimaux, binaires et hexadécimaux, ces derniers étant reconnus comme les plus fréquemment adoptés, utilisés et appliqués dans les domaines de l'informatique moderne et du langage de programmation C#. Nous prendrons également le temps nécessaire pour expliquer, décrire et illustrer les nombreuses façons différentes et spécifiques utilisées pour encoder ou coder des données numériques dans les architectures complexes des micro-ordinateurs modernes, notamment les entiers pouvant être soit signés pour indiquer une polarité, soit non signés pour maximiser l'intervalle de valeurs positives, ainsi que les divers types de nombres réels utilisés pour représenter des valeurs fractionnaires avec précision.
Bref historique
Différents systèmes de numération ont été utilisés depuis l'Antiquité. Cette affirmation est corroborée par le fait que dans l'Égypte ancienne, les gens utilisaient des cadrans solaires, mesurant le temps à l'aide de systèmes de numération. La plupart des historiens pensent que les anciens Égyptiens sont la première civilisation à diviser la journée en parties plus petites. Ils y sont parvenus en utilisant les premiers cadrans solaires, n'étant rien de plus qu'un simple poteau planté dans le sol, orienté en fonction de la longueur et de la direction de l'ombre.
Plus tard, un meilleur cadran solaire a été inventé, ressemblant à la lettre T et divisait le temps entre le lever et le coucher du soleil en 12 parties. Cela prouve l'utilisation du système duodécimal dans l'Égypte ancienne, l'importance du nombre 12 étant généralement liée au fait que les cycles lunaires dans une seule année sont de 12 ou au nombre de phalanges trouvées dans les doigts d'une main (quatre dans chaque doigt, sans compter le pouce).
À l'époque moderne, le système décimal est le système de numération le plus répandu. Peut-être est-ce dû au fait qu'il permet de compter avec les doigts de la main.
Les civilisations antiques divisaient la journée en plusieurs parties plus petites en utilisant différents systèmes de numération - duodécimal et sexagésimal avec des bases 12 et 60 respectivement. Les astronomes grecs comme Hipparque utilisaient des approches astronomiques ayant été utilisées auparavant par les Babyloniens en Mésopotamie. Les Babyloniens effectuaient des calculs astronomiques en utilisant le système sexagésimal, qu'ils avaient hérité des Sumériens, l'ayant développé eux-mêmes vers 2000 avant J.-C. On ne sait pas exactement pourquoi le nombre 60 a été choisi comme base du système de numération, mais il est important de noter que ce système est très approprié pour la représentation des fractions, car le nombre 60 est le plus petit nombre pouvant être divisé par 1, 2, 3, 4, 5, 6, 10, 12, 15, 20 et 30 sans reste.
Applications du système de numération sexagésimal
Le système sexagésimal est encore utilisé aujourd'hui pour mesurer les angles, les coordonnées géographiques et le temps. Il trouve toujours des applications sur le cadran des montres et sur la sphère du globe géographique. Le système sexagésimal a été utilisé par Ératosthène pour diviser une circonférence en 60 parties afin de créer un système primitif de latitudes géographiques, constitué de lignes horizontales passant par des lieux bien connus dans le passé.
Un siècle après Ératosthène, Hipparque a standardisé ces lignes en les rendant parallèles et conformes à la géométrie de la Terre. Il a introduit un système de lignes de longitude géographique, qui comprenaient 360 degrés et passaient respectivement du nord au sud et d'un pôle à l'autre. Dans le livre «Almageste» (150 après J.-C.), Claude Ptolémée a développé les études d'Hipparque en divisant les 360 degrés de latitude et de longitude géographiques en d'autres parties plus petites. Il divisa chacun des degrés en 60 parties égales, chacune d'elles étant ensuite divisée en 60 parties plus petites et égales. Les parties créées par la division furent appelées partes minutiae primae, ou «première minute» et respectivement partes minutiae secundae, ou «seconde minute». Ces parties sont encore utilisées aujourd'hui et sont appelées respectivement «minutes» et «secondes».
Bref résumé
Nous avons fait un petit voyage historique à travers les millénaires, ce qui nous a permis d'apprendre que les systèmes de numération ont été créés, utilisés et développés dès les Sumériens. Les faits présentés expliquent pourquoi un jour ne contient (que) 24 heures, l'heure 60 minutes et la minute 60 secondes. Cela est dû au fait que les anciens Égyptiens divisaient le jour après avoir commencé à utiliser le système de numération duodécimal. La division des heures et des minutes en 60 parties égales est le résultat du travail des astronomes grecs anciens, qui ont effectué leurs calculs en utilisant le système de numération sexagésimal, créé par les Sumériens et utilisé par les Babyloniens.
Le systèmes de numération
Nous avons déjà évoqué l'histoire des systèmes de numération. Voyons maintenant en détail ce qu'ils sont réellement et quel est leur rôle dans l'informatique. Que sont les systèmes de numération ?
Les systèmes de numération sont une manière de représenter des nombres par un ensemble fini de signes graphiques appelés chiffres. Il faut y ajouter les règles de représentation des nombres. Les caractères utilisés pour représenter les nombres dans un système de numération donné peuvent être perçus comme l'alphabet de ce système. Au cours des différentes étapes du développement de la civilisation humaine, divers systèmes de numération ont gagné en popularité. Il faut noter qu'aujourd'hui le plus répandu est le système de numération arabe. Il utilise les chiffres 0, 1, 2, 3, 4, 5, 6, 7, 8 et 9 comme alphabet. (Un fait intéressant est que la représentation des chiffres arabes de nos jours est différente des dix chiffres mentionnés ci-dessus, mais malgré tout, ils se réfèrent toujours au même système de numération - le système décimal).
Outre un alphabet, chaque système de numération a une base. La base est un nombre égal aux différents chiffres utilisés par le système pour représenter les nombres qu'il contient. Par exemple, le système de numération arabe est décimal car il comporte 10 chiffres. Un nombre aléatoire peut être choisi comme base, ayant une valeur absolue différente de 1 et 0. Il peut également s'agir d'un nombre réel ou complexe avec un signe.
Une question pratique que nous pouvons nous poser est la suivante : quel est le meilleur système de numération que nous devrions utiliser ? Pour y répondre, nous devons décider quelle est la manière optimale de représenter un nombre (le nombre de chiffres dans le nombre) et le nombre de chiffres que le système de numération donné utilise - sa base. Mathématiquement, il est possible de prouver que le meilleur rapport entre la longueur de la représentation et le nombre de chiffres utilisés est obtenu en utilisant le nombre d'Euler (e = 2,718281828), étant la base des logarithmes naturels.
Travailler dans un système avec une telle base e est peu pratique car ce nombre ne peut pas être représenté comme un rapport de deux nombres naturels. Cela nous donne des raisons de conclure que la base optimale d'un système de numération est soit 2, soit 3.
Bien que le nombre 3 soit plus proche du nombre de Neper, il n'est pas adapté à la mise en oeuvre technique. Pour cette raison, le système de numération binaire est le seul adapté à une utilisation pratique et il est utilisé dans les ordinateurs et les appareils électroniques modernes.
Systèmes de numération positionnelle
Un système de numération positionnelle est un système dans lequel la position des chiffres est significative pour la valeur du nombre. Cela signifie que la valeur des chiffres du nombre n'est pas strictement définie et dépend de la position du chiffre donné. Par exemple, dans le nombre 351, le chiffre 1 a une valeur de 1, tandis que dans le nombre 1024, il a une valeur de 1000. Il faut noter que les bases des systèmes de numération ne s'appliquent qu'aux systèmes de numération positionnelle. Dans un système de numération positionnelle, le nombre A(p) = (a(n)a(n-1)...a(0),a(-1)a(-2).a(-k)) peut être représenté de la manière suivante :
-k A(p) = ∑ amTm m=n |
Dans cette somme, Tm a la signification d'un facteur de pondération pour le m-ième chiffre du nombre. Dans la plupart des cas, Tm = Pm, ce qui signifie que :
-k A(p) = ∑ amPm m=n |
Formé à partir de la somme ci-dessus, le nombre A(p) est constitué respectivement de sa partie entière (a(n)a(n-1)...a(0)) et de sa fraction (a(-1)a(-2).a(-k)), où chaque a appartient à la multitude des nombres naturels M={0, 1, 2, ..., p-1}. Nous pouvons facilement voir que dans les systèmes de numération positionnelle, la valeur de chaque chiffre est la base du système fois plus grande que celle le précédant (le chiffre de droite, étant le chiffre d'ordre inférieur). En conséquence directe, nous devons ajouter un au chiffre de gauche (d'ordre supérieur), si nous devons noter un chiffre dans le chiffre actuel étant plus grand que la base. Les systèmes avec des bases de 2, 8, 10 et 16 sont devenus très répandus dans les appareils informatiques. Dans le tableau ci-dessous, nous pouvons voir leur notation des nombres de 0 à 15 :
Binaire | Octal | Décimal | Hexadécimal |
---|---|---|---|
0000 | 0 | 0 | 0 |
0001 | 1 | 1 | 1 |
0010 | 2 | 2 | 2 |
0011 | 3 | 3 | 3 |
0100 | 4 | 4 | 4 |
0101 | 5 | 5 | 5 |
0110 | 6 | 6 | 6 |
0111 | 7 | 7 | 7 |
1000 | 10 | 8 | 8 |
1001 | 11 | 9 | 9 |
1010 | 12 | 10 | A |
1011 | 13 | 11 | B |
1100 | 14 | 12 | C |
1101 | 15 | 13 | D |
1110 | 16 | 14 | E |
1111 | 17 | 15 | F |
Systèmes de numération non positionnels
Outre les systèmes de numération positionnels, il existe également des systèmes de numération non positionnels, dans lesquels la valeur de chaque chiffre est une constante et ne dépend pas strictement de sa position dans le nombre. Ces systèmes de numération sont les systèmes de numération romain et grec. Tous les systèmes de numération non positionnels ont un inconvénient commun : la notation des grands nombres dans ces systèmes est très inefficace. En raison de cet inconvénient, ils ne sont que peu utilisés. Cela peut souvent conduire à des imprécisions lors de la détermination de la valeur des nombres. Nous allons examiner très brièvement les systèmes de numération romain et grec.
Système de numération romaine
Le système de numération romaine utilise des séquences des symboles suivants pour représenter les nombres :
Chiffre romain | Valeur décimale |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
Comme nous l'avons déjà mentionné, dans ce système numérique, la position du chiffre n'a aucune importance pour la valeur du nombre et pour déterminer la valeur, les règles suivantes sont appliquées :
- Si deux chiffres romains représentés consécutivement sont dans un ordre tel que la valeur du premier est supérieure ou égale à la valeur du second, leurs valeurs sont additionnées. Exemples : Le nombre III = 3 (1 + 1 + 1). Le nombre MMD = 2500 (2000 + 2000 + 500).
- Si deux chiffres romains représentés consécutivement sont dans l'ordre croissant de leurs valeurs, ils sont soustraits. Cela se fait de droite à gauche. Exemples : Le nombre IX = 9 (-1 + 10), le nombre MXL=1040 (1000 - 10 + 50), mais le nombre MXXIV = 1024 (1000 + 10 + 10 - 1 + 5).
Système de numération grec
Le système de numération grec est un système décimal, dans lequel un groupement de cinq est effectué. Il utilise les chiffres suivants :
Chiffre grec | Valeur décimale |
---|---|
Ι | 1 |
Γ | 5 |
Δ | 10 |
Η | 100 |
Χ | 1 000 |
Μ | 10 000 |
Comme on peut le voir dans le tableau, le nombre 1 est représenté par une ligne verticale, le nombre 5 par la lettre Γ et les puissances de 10 par la première lettre du mot grec correspondant.
Voici quelques exemples de nombres dans ce système :
- ΓΔ = 50 = 5 x 10
- ΓΗ = 500 = 5 x 100
- ΓΧ = 5000 = 5 x 1 000
- ΓΜ = 50,000 = 5 x 10 000
Le système de numération binaire - fondement de la technologie informatique
Le système de numération binaire est le système utilisé pour représenter et traiter les nombres dans les machines informatiques modernes. La principale raison pour laquelle il est si largement répandu est due au fait que les appareils à deux états stables sont très simples à mettre en oeuvre et que les coûts de production des appareils arithmétiques binaires sont très faibles.
Les chiffres binaires 0 et 1 peuvent être facilement représentés dans les machines informatiques comme «courant» et «pas de courant», ou comme «+5 V» et «-5 V». Outre ses avantages, le système binaire de notation des nombres dans les ordinateurs présente également des inconvénients. L'un de ses plus gros défauts pratiques est que les nombres représentés dans le système de numération binaire sont très longs, ce qui signifie qu'ils comportent un grand nombre de bits. Cela le rend peu pratique pour une utilisation directe par les humains. Pour éviter cet inconvénient, des systèmes avec des bases plus grandes sont utilisés dans la pratique.
Nombres décimaux
Les nombres représentés dans le système de numération décimale sont donnés sous une forme primitive, ce qui signifie qu'ils sont faciles à comprendre par les humains. Ce système de numération a pour base le nombre 10. Les nombres qui y sont représentés sont classés par les puissances du nombre 10. Le chiffre le plus petit (le premier de droite à gauche) des nombres décimaux est utilisé pour représenter les unités (100=1), le suivant pour représenter les dizaines (101=10), le suivant pour représenter les centaines (102=100), et ainsi de suite. En d'autres termes, chaque chiffre suivant est dix fois plus grand que celui le précédant. La somme des chiffres séparés détermine la valeur du nombre. Prenons comme exemple le nombre 95031, qui peut être représenté dans le système de numération décimale comme suit :
95031 = (9×104) + (5×103) + (0×102) + (3×101) + (1×100) |
Représenté de cette façon, le nombre 95031 se présente de manière naturelle pour les humains, car les principes du système numérique décimal sont acceptés comme fondamentaux pour les humains.
Les approches évoquées sont également valables pour les autres systèmes numériques. Elles ont le même cadre logique mais sont appliquées à un système avec une base différente. La dernière affirmation est vraie pour les systèmes numériques binaires et hexadécimaux, que nous aborderons en détail dans un instant.
Nombres binaires
Les nombres représentés dans le système de numération binaire sont représentés sous un aspect secondaire, ce qui signifie qu'ils sont faciles à comprendre par la machine informatique. Ils sont un peu plus difficiles à comprendre par les humains. Pour représenter un nombre binaire, on utilise le système de numération binaire, ayant pour base le nombre 2. Les nombres y étant représentés sont classés par puissances de deux. Seuls les chiffres 0 et 1 sont utilisés pour leur notation.
En général, lorsqu'un nombre est représenté dans un système de numération autre que décimal, la base du système de numération est ajoutée comme index entre parenthèses à côté du nombre. Par exemple, avec cette notation 1110(2), nous indiquons un nombre dans le système de numération binaire. Si aucun système de numération n'est explicitement spécifié, il est admis que le nombre est dans le système décimal. Le nombre est prononcé en lisant ses chiffres dans l'ordre de gauche à droite (nous lisons du bit d'ordre le plus élevé au bit d'ordre le plus bas).
Comme pour les nombres décimaux, chaque nombre binaire observé de droite à gauche est représenté par une puissance du nombre 2 dans la séquence respectée. La position d'ordre le plus bas dans un nombre binaire correspond à la puissance zéro (20=1), la deuxième position correspond à 2 à la première puissance (21=2), la troisième position correspond à 2 à la deuxième puissance (22=4), et ainsi de suite. Si le nombre a une longueur de 8 bits, le dernier bit est 2 à la septième puissance (27=128). Si le nombre a 16 bits, le dernier bit est 2 à la quinzième puissance. En utilisant 8 chiffres binaires (0 ou 1), nous pouvons représenter un total de 256 nombres, car 28=256. En utilisant 16 chiffres binaires, nous pouvons représenter un total de 65536 nombres, car 216=65536.
Regardons quelques exemples de nombres dans le système de numération binaire. Prenons par exemple le nombre décimal 148. Il est composé de trois chiffres : 1, 4 et 8, et il correspond au nombre binaire suivant :
10010100(2) 148 = (1×27) + (1×24) + (1×22) |
La notation complète du nombre est représentée dans le tableau suivant :
Nombre | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
---|---|---|---|---|---|---|---|---|
Puissance | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 |
Valeur | 1×27 = 128 | 0×26 = 0 | 0×25 = 0 | 1×24 = 16 | 0×23 = 0 | 1×22 = 4 | 0×21 = 0 | 0×20 = 0 |
La séquence de huit zéros ou uns représente un octet, un nombre binaire ordinaire de huit bits. Tous les nombres de 0 à 255 inclus peuvent être représentés dans un seul octet. Dans la plupart des cas, cela ne suffit pas ; par conséquent, plusieurs octets consécutifs peuvent être utilisés pour représenter un grand nombre. Deux octets forment ce que l'on appelle le "mot machine" (word), correspondant à 16 bits (dans les micro-ordinateurs 16 bits). En plus de cela, les ordinateurs utilisent ce que l'on appelle le double mot ou dword, correspondant à 32 bits.
Si un nombre binaire se termine par 0, il est pair, s'il se termine par 1, il est impair.
Conversion du système de numération binaire au système décimal
Lorsque nous passons du système de numération binaire au système décimal, nous effectuons une conversion d'un nombre binaire en nombre décimal. Chaque nombre peut être converti d'un système de numération à un autre en effectuant une séquence d'opérations possibles dans les deux systèmes de numération. Comme nous l'avons déjà mentionné, les nombres du système binaire sont constitués de chiffres binaires, étant ordonnés par les puissances de 2. Prenons le nombre 11001(2). La conversion en décimal se fait en calculant la somme suivante :
1001(2) = 1×24 + 1×23 + 0×22 + 0×21 + 1×20 = = 16(10) + 8(10) + 1(10) = 25(10) Il en résulte que 11001(2) = 25(10) |
En d'autres termes, chaque chiffre binaire est multiplié par 2 élevé à la puissance de la position dans laquelle il se trouve. À la fin, tous les nombres résultant des chiffres binaires sont additionnés pour obtenir la valeur décimale du nombre binaire.
Schéma de Horner
Il existe une autre méthode de conversion, connue sous le nom de schéma de Horner. Lorsqu'on l'utilise, on multiplie le chiffre le plus à gauche par 2 et on l'ajoute à celui à sa droite. On multiplie ce résultat par deux et on ajoute le chiffre voisin (celui à droite). On répète cette opération jusqu'à ce que tous les chiffres du nombre aient été épuisés et on ajoute le dernier chiffre sans le multiplier. Voici un exemple :
1001(2) = ((1 × 2 + 0) × 2 + 0) × 2 + 1 = 2 × 2 × 2 + 1 = 9 |
Conversion du système décimal au système binaire
Lors de la transition du système décimal au système binaire, nous convertissons un nombre décimal en un nombre binaire. Pour ce faire, nous le divisons par 2 avec un reste. C'est ainsi que nous obtenons le quotient et le reste, étant séparés.
Utilisons à nouveau le nombre 148 comme exemple. Nous effectuons une division entière par la base vers laquelle nous voulons convertir (dans ce cas, il s'agit de 2). Après cela, en utilisant les restes de la division (ils seront toujours soit zéro, soit un), nous représentons le nombre converti. Nous continuons à diviser jusqu'à obtenir un quotient nul. Voici un exemple :
- 148:2 = 74 avec un reste de 0 ;
- 74:2 = 37 avec un reste de 0 ;
- 37:2 = 18 avec un reste de 1 ;
- 18:2 = 9 avec un reste de 0 ;
- 9:2 = 4 avec un reste de 1 ;
- 4:2 = 2 avec un reste de 0 ;
- 2:2=1 avec reste 0 ;
- 1:2=0 avec reste 1 ;
Une fois la division terminée, nous représentons les restes dans l'ordre inverse comme suit :
10010100 exemple 148(10) = 10010100(2) |
Opérations avec des nombres binaires
Les règles arithmétiques d'addition, de soustraction et de multiplication sont valables pour un seul chiffre de nombres binaires :
Addition | Soustraction | Multiplication |
---|---|---|
0 + 0 = 0 | 0 - 0 = 0 | 0 × 0 = 0 |
1 + 0 = 1 | 1 - 0 = 1 | 1 × 0 = 0 |
0 + 1 = 1 | 1 - 1 = 0 | 0 × 1 = 0 |
1 + 1 = 10 | 10 - 1 = 1 | 1 × 1 = 1 |
De plus, avec les nombres binaires, nous pouvons également effectuer des opérations logiques telles que la multiplication logique (conjonction), l'addition logique (disjonction) et la somme modulo deux (ou exclusif).
Il faut également noter que lorsque nous effectuons des opérations arithmétiques avec des nombres d'ordres multiples, nous devons tenir compte de la connexion entre les ordres séparés par transfert ou prêt, lors de l'addition ou de la soustraction respectivement. Examinons quelques détails concernant les opérateurs au niveau du bit.
"Et" au niveau du bit
L'opérateur Et au niveau du bit peut être utilisé pour vérifier la valeur d'un bit donné dans un nombre. Par exemple, si nous voulons vérifier si un nombre donné est pair (nous vérifions si le bit de poids faible est 1) :
10111011 ET 00000001 = 00000001 |
Le résultat est 1, ce qui signifie que le nombre est impair (si le résultat était 0, le nombre serait pair). En C#, le «Et» au niveau du bit est représenté par & et est utilisé comme ceci :
- int result = integer1 & integer2;
"Ou" au niveau du bit
L'opérateur OU au niveau du bit peut être utilisé si nous voulons, par exemple, "élever" un bit donné à 1 :
10111011 OU 00000100 = 10111111 |
Le « ou » au niveau du bit en C# est représenté par | et est utilisé comme ceci :
- int result = integer1 | integer2;
"Ou exclusif" au niveau du bit
L'opérateur au niveau du bit ou exclusif - chaque chiffre binaire est traité séparément, et lorsque nous avons un 0 dans le deuxième opérande, la valeur correspondante du bit dans le premier opérande est copiée dans le résultat. À chaque position qui a une valeur de 1 dans le deuxième opérande, nous inversons la valeur de la position correspondante dans le premier opérande et la représentons dans le résultat :
10111011 OU EXCLUSIF 01010101 = 11101110 |
En C#, la notation de l'opérateur «ou exclusif» est ^ :
- int result = integer1 ^ integer2;
Négation au niveau du bit
L'opérateur au niveau du bit NEGATION est un opérateur unaire, ce ui signifie qu'il s'applique à un seul opérande. Il inverse chaque bit du nombre binaire donné à sa valeur opposée :
NEGATION 10111011 = 01000100 |
En C#, la négation au niveau du bit est représentée par ~ :
- int result = ~integer1;
Nombres hexadécimaux
Avec les nombres hexadécimaux, nous avons le nombre 16 pour une base de système, ce qui implique l'utilisation de 16 chiffres pour représenter toutes les valeurs possibles de 0 à 15 inclus. Comme nous l'avons déjà montré dans l'un des tableaux des sections précédentes, pour noter les nombres dans le système hexadécimal, nous utilisons les chiffres de 0 à 9 et les nombres latins de A à F. Chacun d'eux a la valeur correspondante :
- A=10, B=11, C=12, D=13, E=14, F=15
Nous pouvons donner l'exemple suivant pour les nombres hexadécimaux : D2, 1F2F1, D1E et ainsi de suite.
La transition vers le système décimal se fait en multipliant la valeur du chiffre le plus à droite par 160, celui à gauche par 161, celui à gauche par 162 et ainsi de suite, et en additionnant le tout à la fin. Exemple :
D1E(16) = E × 160 + 1 × 161 + D × 162 = 14 × 1 + 1 × 16 + 13 × 256 = 3358(10) |
La transition du système numérique décimal au système hexadécimal se fait en divisant le nombre décimal par 16 et en prenant les restes dans l'ordre inverse.
Exemple :
- 3358 / 16 = 209 + reste 14 (E)
- 209 / 16 = 13 + reste 1 (1)
- 13 / 16 = 0 + reste 13 (D)
- Nous prenons les restes dans l'ordre inverse et obtenons le nombre D1E(16).
Transition rapide des nombres binaires aux nombres hexadécimaux
La conversion rapide des nombres binaires aux nombres hexadécimaux peut être effectuée rapidement et facilement en divisant le nombre binaire en groupes de quatre bits (en le divisant en demi-octets). Si le nombre de chiffres n'est pas divisible par quatre, les zéros non significatifs des ordres les plus élevés sont ajoutés. Après la division et l'ajout éventuel de zéros, tous les groupes sont remplacés par leurs chiffres correspondants. Voici un exemple :
Regardons ce qui suit : 1110011110(2).
- Nous le divisons en demi-octets et ajoutons les zéros non significatifs. Exemple : 0011 1001 1110.
- Nous remplaçons chaque demi-octet par le chiffre hexadécimal correspondant et nous obtenons 39E(16).
Par conséquent, 1110011110 (2) = 39E(16).
Systèmes de numération : Résumé
En résumé, nous allons reformuler de manière brève mais claire les algorithmes utilisés pour passer d'un système de numération positionnel à un autre :
- Le passage d'un système décimal à un système de numération à base k se fait en divisant consécutivement le nombre décimal à la base du système k et les restes (leur chiffre correspondant dans le système à base k) sont accumulés dans l'ordre inverse.
- Le passage d'un système à base k à un système décimal se fait en multipliant le dernier chiffre du nombre à base k par k0, celui le précédeantpar k1, le suivant par k2 et ainsi de suite, et les produits sont additionnés.
- La transition d'un système numérique basé sur k à un système numérique basé sur p s'effectue par une conversion intermédiaire vers le système décimal (à l'exclusion des systèmes numériques hexadécimaux et binaires).
- La transition d'un système numérique binaire à un système numérique hexadécimal et inversement s'effectue en convertissant chaque séquence de 4 bits binaires en son nombre hexadécimal correspondant et vice versa.
Représentation des nombres
Le code binaire est utilisé pour stocker des données dans la mémoire opérationnelle des machines informatiques. Selon le type de données que nous voulons entreposer (chaînes de caractères, entiers ou nombres réels avec une partie intégrale et fractale), les informations sont représentées d'une manière particulière. Cela est déterminé par le type de données.
Même un programmeur utilisant un langage de programmation de haut niveau doit savoir comment les données sont allouées dans la mémoire opérationnelle de la machine. Cela est également pertinent dans les cas où les données sont stockées sur un support externe, car lors de leur traitement, elles seront situées dans la mémoire opérationnelle.
Dans la section actuelle, nous examinerons les différentes manières de présenter et de traiter différents types de données. En général, elles sont basées sur les concepts de bit, d'octet et de mot machine.
Le bit est une unité binaire d'information dont la valeur est 0 ou 1. Les informations dans la mémoire sont regroupées en séquences de 8 bits, formant un seul octet.
Pour qu'un dispositif arithmétique puisse traiter les données, celles-ci doivent être présentées dans la mémoire par un nombre défini d'octets (2, 4 ou 8), formant un mot machine. Ce sont des concepts que tout programmeur doit connaître et comprendre.
Représentation des nombres entiers dans la mémoire
L'un des points que nous n'avons pas abordés jusqu'à présent est le signe des nombres. Les nombres entiers peuvent être représentés dans la mémoire de deux manières : avec ou sans signe. Lorsque les nombres sont représentés avec un signe, un ordre signé est introduit. Il s'agit de l'ordre le plus élevé et a la valeur 1 pour les nombres négatifs et la valeur 0 pour les nombres positifs. Les autres ordres sont informatifs et ne représentent (contiennent) que la valeur du nombre. Dans le cas d'un nombre sans signe, tous les bits sont utilisés pour représenter sa valeur.
Entiers non signés
Pour les entiers non signés, 1, 2, 4 ou 8 octets sont alloués dans la mémoire. Selon le nombre d'octets utilisés dans la notation d'un nombre donné, différentes portées de représentation de taille variable sont formées. Avec n octets, tous les entiers de la plage [0, 2n-1] peuvent être représentés. Le tableau suivant montre l'intervalle des valeurs des entiers non signés :
Nombre d'octets pour représenter le nombre dans la mémoire | Intervalle | |
---|---|---|
Notation avec ordre | Notation régulière | |
1 | 0 ÷ 28-1 | 0 ÷ 255 |
2 | 0 ÷ 216-1 | 0 ÷ 65 535 |
4 | 0 ÷ 232-1 | 0 ÷ 4 294 967 295 |
8 | 0 ÷ 264-1 | 0 ÷ 18 446 744 073 709 551 615 |
Nous allons donner comme exemple une représentation sur un octet et sur deux octets du nombre 158, dont la notation binaire est la suivante 10011110(2) :
- Représentation sur 1 octet :
- Représentation sur 2 octets :
1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |
Représentation des nombres négatifs
Pour les nombres négatifs, 1, 2, 4 ou 8 octets sont alloués dans la mémoire de l'ordinateur, tandis que le bit de plus haut ordre (le bit le plus à gauche) a une signification de signature et porte l'information sur le signe du nombre. Comme nous l'avons déjà mentionné, lorsque le bit de signature a une valeur de 1, le nombre est négatif, sinon il est positif.
Le tableau suivant montre l'intervalle des valeurs des nombres entiers signés dans l'ordinateur en fonction du nombre d'octets utilisés pour leur notation :
Nombre d'octets pour représenter le nombre dans la mémoire | Intervalle | |
---|---|---|
Notation avec ordre | Notation régulière | |
1 | -27 ÷ 27-1 | -128 ÷ 127 |
2 | -215 ÷ 215-1 | -32 768 ÷ 32 767 |
4 | -231 ÷ 231-1 | -2 147 483 648 ÷ 2 147 483 647 |
8 | -263 ÷ 263-1 | -9 223 372 036 854 775 808 ÷ 9 223 372 036 854 775 807 |
Pour coder les nombres négatifs, on utilise le code direct, inversé et additionnel. Dans ces trois notations, les entiers signés sont compris dans l'intervalle : [-2n-1,2n-1-1]. Les nombres positifs sont toujours représentés de la même manière et les codes direct, inversé et additionnel coïncident tous pour eux.
Le code direct (amplitude signée) est la représentation la plus simple du nombre. Le bit d'ordre le plus élevé porte le signe et les autres bits contiennent la valeur absolue du nombre. Voici quelques exemples :
- Le nombre 3 en amplitude signée est représenté par un nombre de huit bits de long 00000011.
- Le nombre -3 en amplitude signée est représenté par un nombre de huit bits de long 10000011.
Le code inversé (complément à un) est formé à partir de la grandeur signée du nombre par inversion (en remplaçant tous les uns par des zéros et vice-versa). Ce code n'est pas pratique pour les opérations arithmétiques d'addition et de soustraction car il est exécuté d'une manière différente si une soustraction est nécessaire. De plus, les bits porteurs de signe doivent être traités séparément des bits porteurs d'informations. Cet inconvénient est évité en utilisant un code supplémentaire qui, au lieu de soustraire, implémente l'addition avec un nombre négatif. Ce dernier est représenté par son addition, c'est-à-dire la différence entre 2n et le nombre lui-même. Exemple :
Le nombre -127 en magnitude signée est représenté par 1 1111111 et en complément à un par 1 0000000.
Le nombre 3 en magnitude signée est représenté par 0 0000011 et en complément à un ressemble à 0 1111100.
Le code supplémentaire (complément à deux) est un nombre en code inversé auquel on ajoute un (par addition). Exemple : Le nombre -127 est représenté avec le code supplémentaire par 1 0000001.
Dans le code décimal codé binaire, également connu sous le nom de code BCD, deux chiffres décimaux sont enregistrés dans un octet. Cela est réalisé en codant un seul chiffre décimal dans chaque demi-octet. Les nombres présentés de cette manière peuvent être condensés, ce qui signifie qu'ils peuvent être représentés dans un format condensé. Si nous représentons un seul chiffre décimal dans un octet, nous obtenons un format non condensé. Les microprocesseurs modernes utilisent un ou plusieurs des codes décrits pour présenter les nombres négatifs, la méthode la plus répandue étant l'utilisation du complément à deux.
Types d'entiers en C#
En C#, il existe huit types de données entiers signés ou non signés. Selon la quantité d'octets alloués à chaque type, différentes intervalles de valeurs sont déterminées. Voici les descriptions des types :
Type | Taille | Intervalle | Type dans le cadre d'application .NET |
---|---|---|---|
sbyte | 8 bits | -128 ÷ 127 | System.SByte |
byte | 8 bits | 0 ÷ 255 | System.Byte |
short | 16 bits | -32 768 ÷ 32 767 | System.Int16 |
ushort | 16 bits | 0 ÷ 65 535 | System.UInt16 |
int | 32 bits | -2 147 483 648 ÷ 2 147 483 647 | System.Int32 |
uint | 32 bits | 0 ÷ 4 294 967 295 | System.UInt32 |
long | 64 bits | -9 223 372 036 854 775 808 ÷ 9 223 372 036 854 775 807 | System.Int64 |
ulong | 64 bits | 0 ÷ 18 446 744 073 709 551 615 | System.UInt64 |
Nous allons examiner brièvement les plus utilisés. Le type entier le plus couramment utilisé est int. Il est représenté par un nombre de 32 bits avec un complément à deux et prend une valeur dans l'intervalle [-231, 231-1]. Les variables de ce type sont le plus souvent utilisées pour effectuer des boucles, des tableaux d'index et d'autres calculs d'entiers. Dans le tableau suivant, un exemple de déclaration d'une variable de type int est présenté :
Le type long est le plus grand type d'entier signé en C#. Il a une taille de 64 bits (8 octets). Lorsque l'on donne une valeur aux variables de type long, les lettres latines «l» ou «L» sont placées à la fin du littéral entier. Placé à cette position, ce modificateur signifie que le littéral a une valeur de type long. Cela est fait parce que par défaut, tous les littéraux entiers sont de type int. Dans l'exemple suivant, nous déclarons et donnons une valeur de 64 bits aux variables de type long :
Une condition importante est de ne pas dépasser l'intervalle de nombres pouvant être représentés dans le type utilisé. Cependant, C# offre la possibilité de contrôler ce qui se passe lorsqu'un dépassement se produit. Cela se fait via les blocs checked et unchecked. Les premiers sont utilisés lorsque l'application doit lever une exception (du type System.OverflowException) en cas de dépassement de l'intervalle de la variable. Le code de programmation suivant fait exactement cela :
Si le fragment se trouve dans un bloc non vérifié, aucune exception ne sera levée et le résultat de sortie sera erroné :
-2147483648Si ces blocs ne sont pas utilisés, le compilateur C# fonctionne par défaut en mode non coché.
C# inclut des types non signés, ce qui peut être utile lorsqu'un intervalle plus large est nécessaire pour les variables dans la portée des nombres positifs. Vous trouverez ci-dessous quelques exemples de déclaration de variables sans signe. Nous devons faire attention aux suffixes de ulong (toutes les combinaisons de U, L, u, l).
Représentation Petit-boutiste (Little Endian) et Gros-boutiste (Big Endian)
Il existe deux façons de classer les octets dans la mémoire lorsqu'ils représentent des entiers de plus d'un octet :
- Petit-boutiste (LE) : les octets sont classés de gauche à droite, du plus petit au plus grand ordre. Cette représentation est utilisée dans l'architecture des microprocesseurs Intel x86 et Intel x64.
- Gros-boutiste (BE) : les octets sont classés de gauche à droite, en commençant par le plus grand ordre et en terminant par le plus petit. Cette représentation est utilisée dans l'architecture des microprocesseurs PowerPC, SPARC et ARM.
Voici un exemple : le nombre A7B6EA72(16) est présenté dans les deux ordres d'octets de la manière suivante :

Certaines classes de C# offrent la possibilité de définir l'ordre standard à utiliser. Ceci est important pour des opérations telles que l'envoi/la réception de flux d'informations sur Internet ou d'autres types de communication entre des appareils fabriqués selon des normes différentes. Le champ IsLittleEndian de la classe BitConverter, par exemple, indique dans quel mode la classe fonctionne et comment elle entrepose les données sur l'architecture informatique actuelle.
Représentation des nombres réels à virgule flottante
Les nombres réels sont constitués d'un entier et de parties fractionnaires. Dans les micro-ordinateurs, ils sont représentés sous forme de nombres à virgule flottante. En fait, cette représentation provient de la norme pour l'arithmétique à virgule flottante (IEEE 754), adoptée par les principaux fabricants de microprocesseurs. La plupart des plates-formes matérielles et des langages de programmation permettent ou exigent que les calculs soient effectués conformément aux exigences de cette norme. La norme définit :
- Formats arithmétiques : un ensemble de données binaires et décimales à virgule flottante, se composant d'un nombre fini de chiffres.
- Formats d'échange : codage (séquences de bits), pouvant être utilisés pour l'échange de données sous une forme efficace et compacte.
- Algorithmes d'arrondi : méthodes utilisées pour arrondir les nombres au cours des calculs.
- Opérations : opérations arithmétiques et autres opérations des formats arithmétiques.
- Exceptions : ce sont des signaux pour des événements extraordinaires tels que la division par zéro, le débordement et autres.
Selon la norme IEEE-754, un nombre réel aléatoire R peut être présenté de la manière suivante :
R = M × qp |
où M est la mantisse du nombre, p est l'ordre (exposant) et q est en conséquence la base du système numérique dans lequel se trouve le nombre. La mantisse doit être une fraction commune positive ou négative |M|<1, et l'exposant - un entier positif ou négatif.
Dans la méthode de représentation des nombres mentionnée, chaque nombre à virgule flottante aura le format résumé suivant ±0,M×q±p.
Lorsque l'on note des nombres au format à virgule flottante en utilisant notamment le système numérique binaire, on aura R = M × 2p. Dans cette représentation des nombres réels dans la mémoire de l'ordinateur, lorsque l'on change l'exposant, le point décimal de la mantisse se déplace («flottante»). Le format de représentation à virgule flottante a une forme semi-logarithmique. Il est représenté dans la figure suivante :

Représentation des nombres à virgule flottante
Donnons un exemple de la manière dont un nombre à virgule flottante est représenté dans la mémoire. Nous voulons écrire le nombre -21,15725 au format à virgule flottante 32 bits (simple précision) selon la norme IEEE-754. Dans ce format, 23 bits sont utilisés pour la mantisse, 8 bits pour l'exposant et 1 bit pour le signe.
Le signe du nombre est négatif, ce qui signifie que la mantisse a un signe négatif :
S = -1 |
L'exposant a une valeur de 4 (représentée avec un ordre décalé) :
p = (20 + 21 + 27) - 127 = (1+2+128) - 127 = 4 |
Pour passer à la valeur réelle, nous soustrayons 127 du code supplémentaire car nous travaillons avec 8 bits (127 = 27-1) à partir de la position zéro.
La mantisse a la valeur suivante (sans tenir compte du signe).
M = 1 + 2-2 + 2-4 + 2-7 + 2-9 = = 1 + 0.25 + 0.0625 + 0.0078125 + 0.001953125 = = 1.322265625 |
Il faut noter que nous avons ajouté un 1, manquant dans la notation binaire de la mantisse. Nous l'avons fait parce que la mantisse est toujours normalisée et commence par un 1 par défaut.
La valeur du nombre est calculée à l'aide de la formule R = M * 2p, dans notre exemple ressemblant à ceci :
R = -1,3222756 × 24 = -1,322275625 × 16 = -21,1572496 ≈ -21,15725 |
Normalisation de la mantisse
Pour utiliser la grille d'ordre plus pleinement, la mantisse doit contenir un 1 dans son ordre de plus grande puissance. Chaque mantisse remplissant cette condition est dite normalisée. Dans la norme IEEE-754, le 1 dans la partie entière de la mantisse est par défaut, ce qui signifie que la mantisse est toujours un nombre compris entre 1 et 2.
Si pendant les calculs un résultat ne remplissant pas cette condition est atteint, cela signifie que la normalisation est violée. Cela nécessite la normalisation du nombre avant son traitement ultérieur, et pour cela, le point décimal dans la mantisse est déplacé et le changement d'ordre correspondant est effectué.
Les types de données float et double en C#
En C#, nous disposons de deux types pouvant représenter des nombres à virgule flottante. Le type float est un nombre réel de 32 bits avec une virgule flottante et il est accepté comme nombre à virgule flottante de simple précision. Le type double est un nombre réel de 64 bits avec une virgule flottante et il est accepté comme nombre à virgule flottante de double précision. Ces types de données réels et les opérations arithmétiques les accompagnant correspondent à la spécification décrite par la norme IEEE 754-1985. Dans le tableau suivant sont présentées les caractéristiques les plus importantes des deux types de données :
Type de données | Taille | Intervalle | Chiffres significatifs | Type dans .NET Framework |
---|---|---|---|---|
float | 32 bits | ±1.5 × 10-45 ÷ ±3.4 × 1038 | 7 | System.Single |
double | 64 bits | ±5.0 × 10-324 ÷ ±1.7 × 10308 | 15 à 16 | System.Double |
Dans le type de données float, nous avons une mantisse, contenant 7 chiffres significatifs, tandis que dans le type double, elle entrepose 15 à 16 chiffres significatifs. Les bits restants sont utilisés pour spécifier le signe de la mantisse et la valeur de l'exposant. Le type double, outre le plus grand nombre de chiffres significatifs, a également un exposant plus grand, ce qui signifie qu'il a une plus grande portée des valeurs qu'il peut assumer. Voici un exemple de déclaration de variables de types float et double :
Les suffixes placés après les nombres du côté droit de l'équation servent à spécifier le type de nombre à traiter (f pour float, d pour double). Dans ce cas, ils sont en place car par défaut, 5.0 sera interprété comme un double et 5 - comme un int.
En C#, les littéraux de nombres à virgule flottante sont par défaut de type double.
Les entiers et les nombres à virgule flottante peuvent tous deux être présents dans une expression donnée. Dans ce cas, les variables entières sont converties en variables à virgule flottante et le résultat est défini selon les règles suivantes :
- Si l'un des types à virgule flottante est un double, le résultat sera double (ou bool).
- S'il n'y a pas de type double dans l'expression, le résultat est float (ou bool).
De nombreuses opérations mathématiques peuvent donner des résultats n'ayant pas de valeur numérique spécifique, comme la valeur «+/- infini» ou NaN (signifiant «Not a Number»), ces valeurs ne sont pas des nombres. Voici un exemple :
Si nous l'exécutons, nous obtenons le résultat suivant :
0.0Infinity
-Infinity
NaN
Si nous exécutons le code ci-dessus en utilisant int au lieu de double, nous recevrons une exception System.DivideByZeroException, car la division entière par 0 n'est pas une opération autorisée.
Erreurs lors de l'utilisation de nombres à virgule flottante
Les nombres à virgule flottante (présentés selon la norme IEEE 754) sont très pratiques pour les calculs en physique, où de très grands nombres sont utilisés (avec plusieurs centaines de chiffres) et également des nombres très proches de zéro (avec des centaines de chiffres après la virgule décimale avant le premier chiffre significatif). Lorsque vous travaillez avec ces nombres, le format IEEE 754 est exceptionnellement pratique car il conserve l'ordre du nombre dans l'exposant et la mantisse n'est utilisée que pour entreposer les chiffres significatifs. Dans les nombres à virgule flottante 64 bits, une précision de 15 à 16 chiffres, ainsi que des exposants déplaçant la virgule décimale de 300 positions à gauche ou à droite, peuvent être obtenus.
Malheureusement, tous les nombres réels n'ont pas une représentation exacte au format IEEE 754, car tous les nombres ne peuvent pas être présentés comme un polynôme d'un nombre fini d'additions, qui sont des puissances négatives de deux. Ceci est tout à fait valable même pour les nombres, étant utilisés quotidiennement pour les calculs financiers les plus simples. Par exemple, le nombre 0,1 représenté comme une valeur à virgule flottante de 32 bits est présenté comme 0,099999994. Si l'on utilise l'arrondi approprié, le nombre peut être accepté comme 0,1, mais l'erreur peut s'accumuler et provoquer de graves écarts, en particulier dans les calculs financiers. Par exemple, en additionnant 1 000 articles avec un prix unitaire de 0,1 CAD chacun, nous devrions obtenir une somme de 100 CAD, mais si nous utilisons des nombres à virgule flottante de 32 bits pour les calculs, le résultat sera 99,99905. Voici un exemple en C# en action, qui prouve les erreurs causées par la présentation inexacte des nombres réels décimaux dans le système de numération binaire :
Nous pouvons facilement voir les erreurs dans de tels calculs si nous exécutons l'exemple ou le modifions pour obtenir des erreurs encore plus frappantes.
Précision des nombres à virgule flottante
La précision des résultats des calculs à virgule flottante dépend des paramètres suivants :
- Précision de la représentation des nombres.
- Précision des méthodes numériques utilisées.
- Valeur des erreurs résultant de l'arrondi,...
Les calculs avec ces méthodes peuvent être inexacts car elles sont représentées dans la mémoire avec une certaine précision. Prenons l'exemple du fragment de code suivant :
Pendant l'exécution, dans la boucle, nous ajoutons la valeur 1/10 à la variable sum. Lors de l'appel de la méthode WriteLine(), nous utilisons le spécificateur de format aller-retour "{0:r}" pour imprimer la valeur exacte (non arrondie) contenue dans la variable, puis nous affichons la même valeur sans spécifier de format. Nous nous attendons à ce que lorsque nous exécutons le programme, nous obtenions 1,0 comme résultat, mais en réalité, lorsque l'arrondi est désactivé, le programme renvoie une valeur très proche de la valeur correcte mais toujours différente :
0.999999999999999891
Comme nous pouvons le voir dans l'exemple, par défaut, lors de l'impression de nombres à virgule flottante dans .NET Framework, ils sont arrondis, ce qui semble réduire les erreurs de leur notation inexacte dans le format IEEE 754. Le résultat du calcul ci-dessus est évidemment erroné, mais après l'arrondi, il semble correct. Cependant, si nous ajoutons 0,1 plusieurs milliers de fois, l'erreur s'accumulera et l'arrondi ne pourra pas la compenser.
La raison de la mauvaise réponse dans l'exemple est que le nombre 0,1 n'a pas de représentation exacte dans le type de données double et qu'il doit être arrondi. Remplaçons double par float :
Si nous exécutons le code ci-dessus, nous obtiendrons une somme entièrement différente :
1.00000012Encore une fois, la raison en est l'arrondi.
Si nous examinons pourquoi le programme donne ces résultats, nous verrons que le nombre 0,1 de type de données float. Tout cela semble correct sauf pour la mantisse, qui a une valeur légèrement supérieure à 1,6, pas exactement 1,6 car ce nombre ne peut pas être présenté comme la somme des puissances négatives de 2. Si nous devons être très précis, la valeur de la mantisse est 1 + 1 / 2 + 1 / 16 + 1 / 32 + 1 / 256 + 1 / 512 + 1 / 4096 + 1 / 8192 + 1 / 65536 + 1 / 131072 + 1 / 1048576 + 1 / 2097152 + 1 / 8388608 ≈ 1,60000002384185791015625 ≈ 1.6. Ainsi, le nombre 0,1 présenté dans la norme IEE 754 est légèrement supérieur à 1,6 × 2-4 et l'erreur ne se produit pas pendant l'addition mais avant celle-ci, lorsque 0,1 est enregistré dans le type de données float.
Les types de données Double et Float ont un champ appelé Epsilon, étant une constante, et il contient la plus petite valeur supérieure à zéro, qui peut être représentée par une instance de System.Single ou System.Double respectivement. Chaque valeur inférieure à Epsilon est considérée comme égale à 0. Par exemple, si nous comparons deux nombres, étant différents après tout, mais dont la différence est inférieure à Epsilon, ils seront considérés comme égaux.
Le type décimal
Le type System.Decimal dans .NET Framework utilise l'arithmétique décimale à virgule flottante et une précision de 128 bits, ce qui est très adapté aux grands nombres et aux calculs financiers précis. Voici quelques caractéristiques du type decimal :
Type | Taille | Intervalle | Nombres significatifs | Type dans la cadre d'application .NET |
---|---|---|---|---|
decimal | 128 bits | ±1.0 × 10-28 ÷ ±7.9 × 1028 | 28 à 29 | System.Decimal |
Contrairement aux nombres à virgule flottante, le type decimal conserve sa précision pour tous les nombres décimaux d'intervalle. Le secret de cette excellente précision lorsque l'on travaille avec des nombres décimaux réside dans le fait que la représentation interne de la mantisse n'est pas dans le système binaire mais dans le système décimal. L'exposant est également une puissance de 10, et non de 2. Cela permet de représenter les nombres avec précision, sans qu'ils soient convertis dans le système numérique binaire.
Étant donné que les types float et double et les opérations sur eux sont implémentés par le coprocesseur arithmétique, faisant partie de tous les microprocesseurs informatiques modernes, et que le type décimal est implémenté par le logiciel dans .NET CLR, il est dix fois plus lent que le type double, mais il est irremplaçable pour l'exécution de calculs financiers.
Si notre objectif est d'assigner un littéral donné à une variable de type decimal, nous devons utiliser les suffixes m ou M. Par exemple :
Utilisons décimal au lieu de float/double dans l'exemple précédent :
Cette fois-ci, le résultat est exactement celui que nous attendions :
1.0000000Bien que le type décimal ait une précision supérieure à celle des types à virgule flottante, son intervalle de valeurs est plus petite et, par exemple, il ne peut pas être utilisé pour représenter la valeur suivante 1e-50. Par conséquent, un dépassement de capacité peut se produire lors de la conversion de nombres à virgule flottante en nombre décimal.
Données de caractères (chaînes de caractères)
Les données de caractères (texte) en informatique sont du texte, codé à l'aide d'une séquence d'octets. Il existe différents schémas de codage utilisés pour coder les données de texte. La plupart d'entre eux codent un caractère dans un octet ou dans une séquence de plusieurs octets. Ces schémas de codage sont ASCII, Windows-1251, UTF-8 et UTF-16.
Schémas de codage (codages)
Le schéma de codage ASCII compare le nombre unique de lettres de l'alphabet latin et d'autres symboles et caractères spéciaux et les écrit dans un seul octet. La norme ASCII contient un total de 127 caractères, chacun étant écrit dans un octet. Un texte écrit sous forme de séquence d'octets selon la norme ASCII ne peut pas contenir de caractères cyrilliques ou d'autres alphabets tels que l'arabe, le coréen et le chinois.
Comme la norme ASCII, le schéma de codage Windows-1251 compare le nombre unique de lettres de l'alphabet latin, cyrillique et de certains autres symboles et caractères spécialisés et les écrit sur un octet. Le codage Windows-1251 définit le nombre de 256 caractères, soit exactement autant que de valeurs différentes qui peuvent être écrites sur un octet. Un texte écrit selon la norme Windows-1251 ne peut contenir que des lettres cyrilliques et latines, les lettres arabes, indiennes ou chinoises ne sont pas prises en charge.
Le codage UTF-8 est complètement différent. Tous les caractères de la norme Unicode - les lettres et symboles utilisés dans toutes les langues largement répandues dans le monde (cyrillique, latin, arabe, chinois, japonais, coréen et de nombreuses autres langues et systèmes d'écriture) - peuvent y être codés. Le codage UTF-8 contient plus d'un demi-million de symboles. Dans le codage UTF-8, les symboles les plus fréquemment utilisés sont codés sur 1 octet (lettres latines et chiffres par exemple), les seconds symboles les plus fréquemment utilisés sont codés sur 2 octets (lettres cyrilliques par exemple), et ceux étant encore plus rarement utilisés sont codés sur 3 ou 4 octets (comme les alphabets chinois, japonais et coréen).
Le codage UTF-16, comme UTF-8, peut représenter du texte de toutes les langues et systèmes d'écriture couramment utilisés, décrits dans la norme Unicode. Dans UTF-16, chaque symbole est écrit sur 16 bits (2 octets) et certains des symboles les plus rarement utilisés sont présentés sous la forme d'une séquence de deux valeurs de 16 bits.
Présentation d'une séquence de caractères
Les séquences de caractères peuvent être présentées de plusieurs manières. La méthode la plus courante pour écrire du texte dans la mémoire consiste à écrire 2 ou 4 octets de sa longueur, suivis d'une séquence d'octets, présentant le texte lui-même dans une sorte de codage (par exemple Windows-1251 ou UTF-8).
Une autre méthode, moins courante, d'écriture de textes en mémoire, typique du langage de programmation C, représente les textes sous forme d'une séquence de caractères, généralement codés sur 1 octet, suivis d'un caractère de fin spécial, le plus souvent un 0. Lors de l'utilisation de cette méthode, la longueur du texte enregistré à une position donnée dans la mémoire n'est pas connue à l'avance. Cela est considéré comme un inconvénient dans de nombreuses situations.
Type de données char
Le type char dans le langage C# est une valeur de 16 bits, dans laquelle un seul caractère Unicode ou une partie de celui-ci est codé. Dans la plupart des alphabets (par exemple ceux utilisés par toutes les langues européennes), une lettre est écrite dans une seule valeur de 16 bits, et on suppose donc qu'une variable de type de données char représente un seul caractère. Voici un exemple :
Le type de données string
Le type de données string en C# contient du texte, codé en UTF-16. Une chaîne unique en C# se compose d'une longueur de 4 octets et d'une séquence de caractères écrits sous forme de valeurs 16 bits de type de données char. Le type de données string peut entreposer des textes écrits dans tous les alphabets et systèmes d'écriture courants : latin, cyrillique, chinois, japonais, arabe et bien d'autres. Voici un exemple d'utilisation de la chaîne de caractères :