Archives Wild Code School
C#

1. Les nombres entiers

Quête 8 sur 46 · 1 image archivée

Après cette quête, tu sauras comment créer des entiers et effectuer des opérations

Objectifs

  • Savoir reconnaître une ligne d'instruction en C#

  • Connaître les tailles et les valeurs maximum

  • Connaître les noms des types et la taille qu'ils représentent

  • Effectuer des opérations sur les entiers

  • Convertir explicitement une variable

Maîtriser la matrice

Comprendre comment réfléchit la Matrice n'est pas tout. Il faut aussi que tu apprennes à la contrôler pour qu'elle réalise tous tes désirs.

Tu as à ta disposition ta maîtrise des arts obscurs, des arcanes des systèmes informatiques. Il ne te reste plus qu'à t'en servir pour battre la Matrice à plates coutures.

Déclarer une variable entière

C# est un langage fortement typé. C'est-à-dire que, lorsque tu déclares une variable, tu dois absolument spécifier son type, lequel ne changera pas tout au long de l'exécution du programme. Il y a une syntaxe quasi commune à tous les langages fortement typés inspirés du C, qui est l'ancêtre des langages tels qu'on les connaît aujourd'hui.

Syntaxe de la déclaration de variable en C# :

shell
[type de la variable] [nom de la variable] ;

L'opérateur = permet d'affecter une valeur à la variable.

Lors d'une déclaration :

shell
[type de la variable] [nom de la variable] = [valeur de la variable] ;

Après la déclaration :

shell
[type de la variable] [nom de la variable] ;
[nom de la variable] = [valeur de la variable] ;

Décortiquons un peu la syntaxe que je viens de te montrer. Ce qu'il y a entre crochets est à spécifier par toi. Tu remarques qu'à chaque fin de ligne, il y a un point-virgule. Le point-virgule sépare des instructions. Il dit à ton compilateur : voici la fin de mon instruction.

En C#, le point-virgule est crucial. Si tu l'oublies, ton programme ne compilera pas, se plaignant que tu as oublié le point-virgule (et crois-moi, ça risque de t'arriver souvent !).

Les tailles d'entiers

Une différence majeure existe entre notre esprit et celui d'un ordinateur. Outre le fait que les circuits des ordinateurs ne leur permettent pas de ressentir des émotions, ils sont incapables de se représenter l'infini. Même plus qu'incapables, il n'en ont aucune notion. Les ordinateurs ont leur limite de représentation de nombres, et cela est dû à leur fonctionnement interne.

Comme une valeur est codée sur un certain nombre de *bits, elle a donc un maximum. Au-delà de ce maximum, la représentation n'est plus bonne. Quand c'est le cas, le système envoie une exception et le programme s'arrête. Il s'agit d'un overflow ou dépassement de capacité.

C# (et les autres langages compilés) permet de manipuler des types de nombres entiers plus ou moins grands.

Ci-dessous un tableau de correspondance type - taille en bits et valeurs minimum/maximum.

Type Taille Minimum Maximum
byte 8 bits 0 255
short 16 bits -32 768 32 768
int 32 bits -2 147 483 647 2 147 483 647
long 64 bits -9 223 372 036 854 775 808 9 223 372 036 854 775 808

Comme le tableau ci-dessus le démontre, la taille maximum que l'on peut avoir pour un entier est de 64 bits, ce qui permet un très grand nombre de valeurs. Mais si cela ne suffit pas, inutile d'inventer un entier sur 128 bits. Il suffit de mettre à disposition des entiers non-signés. C'est un entier qui ne pourra qu'être positif. Du coup, on double la capacité de stockage d'un entier. On préfixe le type avec u pour avoir sa version non signée. uint pour entier sur 32 bits non-signé, ulong pour un entier sur 64 bits non-signé ...

Bon, assez de théorie ! On passe quand à la pratique ?

↗
MSDN - Les types d'entiers
docs.microsoft.com

Les opérations sur les entiers

Bien, maintenant que l'on dispose du bagage théorique, on peut commencer un petit semblant de codage.

Tout comme en mathématiques, en informatique on réalise des opérations entre les opérandes. En mathématiques, sur l'ensemble des entiers naturels, on dénombre quatre opérations basiques :

  • L'addition : opérateur +

  • La multiplication : opérateur ×

  • La division : opérateur ÷

  • La soustraction: opérateur -

Eh bien en informatique, sur l'ensemble des entiers, nous reconnaissons les mêmes opérations, mais certaines avec des représentations différentes :

  • L'addition : opérateur +

  • La soustraction : opérateur -

  • La multiplication : opérateur *

  • La division : opérateur /

Ainsi:

cs
short operand1 = 5;
short operand2 = -2;
short operandsAdditionResult = operand1 + operand2; // = 3
// short substractionResult = (operandsAdditionResult - operand2) + 32 763; <-- Mauvaise représentation du nombre
int substractionResult = (operandsAdditionResult - operand2) + 32 763; // = 32 769
short multiplicationResult = operand1 * operand2; // = -10
short divisionResult = multiplicationResult / operand2; // = 5;

Conversion explicite

Dans un langage fortement typé, il arrive souvent que nous désirions passer d'un type à un autre. Deux types de conversion de type sont à notre disposition en C#: les conversions **explicites **et les conversions implicites.

Une conversion **explicite **est utilisée pour informer le compilateur qu'une conversion d'un type dans un autre risque de provoquer une perte de donnée. C'est l'_inverse _d'une conversion _implicite _où l'on est sûr qu'_aucune _donnée ne sera perdue pendant la conversion.

A quoi peut donc bien servir une conversion explicite dans ce cas ?

Il arrive souvent que nous disposons d'une valeur et que nous ne voulons pas changer son contenu mais uniquement la manière de le lire. Par exemple

cs
int x = 23;
short y = 0;
y = x;

L'exemple ci-dessus ne compile pas. L'erreur est la suivante:

javascript
Cannot implicitly convert type `int' to `short'. An explicit conversion exists (are you missing a cast?)

La description de l'erreur nous indique qu'il est impossible pour le compilateur C# de convertir implicitement une variable de type int en variable de type short. En effet, la taille d'un int est deux fois supérieure à la taille d'un short. Donc faire rentrer un int dans un short est chose impossible puisque le int ne rentre pas dans le short. Si une conversion _implicite _était réalisée, nous perdrions à coup sûr 2 octets d'informations.

Ca veut dire que je suis coincé ?

Et bien non ! Lorsqu'on lit la suite de la description de l'erreur, le compilateur nous propose une solution:

javascript
An explicit conversion exists (are you missing a cast?)

Le compilateur nous dit qu'il existe une conversion explicite. Il nous demande même si nous n'avons pas oublié un cast.

C'est quoi un cast ?

Un cast est tout simplement l'opération de conversion explicite. Un cast passe un type dans un autre, en tronquant éventuellement une partie des données castées pour que le variable d'un autre type puisse être affectée. Bien sûr, **caster **une variable peut-être dangereux et le risque de perte d'information est sûr à 100%, mais dans le cas d'un passage de int à short, si l'on est sûr que la valeur contenue dans notre int ne dépasse pas la taille du short nous n'avons absolument aucun souci à nous faire.

cs
int x = 23;
short y = 0;
x = (short)y;

L'exemple ci-dessus compile. Nous avons suivi les conseils du compilateur et nous avons casté notre variable x de type int en type short pour pouvoir l'assigner à y. Et voilà, la magie opère: nous avons fait rentrer un int dans un short. Bien entendu, si la valeur de x _dépasse _la capacité de y, y vaudra le maximum possible pour son type. Et pour cette raison, il faut être très attentif lorsque l'on réalise un cast pour ne perdre aucune information.

↗
MSDN - Conversions de type

Lire la partie "Conversions explicites"

docs.microsoft.com

Challenge

Additions

Écris un programme qui instancie trois variables à leur valeur maximum :

  • x -> en type int = int.MaxValue

  • y -> en type long = long.MaxValue

  • z -> en type short = short.MaxValue

Additionne les trois dans une variable du type qui a suffisamment de bits pour coder le résultat de l'opération.

Critères de validation

  • Un lien vers ta solution sur GitHub

  • L'addition est explicitement convertie vers le type de la variable qui stocke son résultat