Opérateurs arithmétiques (référence C#)
Les opérateurs suivants effectuent des opérations arithmétiques avec des opérandes de types numériques :
- Opérateurs unaires
++
(incrément),--
(décrément),+
(plus) et-
(moins) - Opérateurs binaires
*
(multiplication),/
(division),%
(reste),+
(addition) et-
(soustraction)
Ces opérateurs sont pris en charge par tous les types numériques intégraux et à virgule flottante.
Dans le cas des types intégraux, ces opérateurs (à l’exception des opérateurs ++
et --
) sont définis pour les types int
, uint
, long
et ulong
. Lorsque les opérandes sont d’autres types intégraux (sbyte
, byte
, short
, ushort
ou char
), leurs valeurs sont converties en valeurs de type int
, qui est également le type de résultat d’une opération. Lorsque des opérandes sont de types intégraux ou à virgule flottante différents, leurs valeurs sont converties en type contenant le plus proche, s’il existe un tel type. Pour plus d’informations, consultez la section Promotions numériques de la spécification du langage C#. Les opérateurs ++
et --
sont définis pour tous les types numériques intégraux et à virgule flottante, ainsi que pour le type char . Le type de résultat d’une expression d’affectation composée est le type de l’opérande de gauche.
Opérateur d’incrémentation ++
L’opérateur d’incrémentation unaire ++
incrémente son opérande de 1. L’opérande doit être une variable, un accès propriété ou un accès indexeur.
L’opérateur d’incrémentation est pris en charge sous deux formes : l’opérateur d’incrémentation suffixé, x++
, et l’opérateur d’incrémentation préfixé, ++x
.
Opérateur d'incrément suffixé
Le résultat de x++
est la valeur de x
avant l’opération, comme le montre l’exemple suivant :
int i = 3;
Console.WriteLine(i); // output: 3
Console.WriteLine(i++); // output: 3
Console.WriteLine(i); // output: 4
Opérateur d'incrémentation préfixé
Le résultat de ++x
est la valeur de x
après l’opération, comme le montre l’exemple suivant :
double a = 1.5;
Console.WriteLine(a); // output: 1.5
Console.WriteLine(++a); // output: 2.5
Console.WriteLine(a); // output: 2.5
Opérateur de décrémentation --
L’opérateur de décrémentation unaire --
décrémente son opérande de 1. L’opérande doit être une variable, un accès propriété ou un accès indexeur.
L’opérateur de décrémentation est pris en charge sous deux formes : l’opérateur de décrémentation suffixé, x--
, et l’opérateur de décrémentation préfixé, --x
.
Opérateur de décrémentation suffixé
Le résultat de x--
est la valeur de x
avant l’opération, comme le montre l’exemple suivant :
int i = 3;
Console.WriteLine(i); // output: 3
Console.WriteLine(i--); // output: 3
Console.WriteLine(i); // output: 2
Opérateur de décrémentation préfixé
Le résultat de --x
est la valeur de x
après l’opération, comme le montre l’exemple suivant :
double a = 1.5;
Console.WriteLine(a); // output: 1.5
Console.WriteLine(--a); // output: 0.5
Console.WriteLine(a); // output: 0.5
Opérateurs plus et moins unaires
L’opérateur unaire +
retourne la valeur de son opérande. L’opérateur unaire -
calcule la négation numérique de son opérande.
Console.WriteLine(+4); // output: 4
Console.WriteLine(-4); // output: -4
Console.WriteLine(-(-4)); // output: 4
uint a = 5;
var b = -a;
Console.WriteLine(b); // output: -5
Console.WriteLine(b.GetType()); // output: System.Int64
Console.WriteLine(-double.NaN); // output: NaN
Le type ulong ne prend pas en charge l’opérateur unaire -
.
Opérateur de multiplication *
L’opérateur de multiplication *
calcule le produit de ses opérandes :
Console.WriteLine(5 * 2); // output: 10
Console.WriteLine(0.5 * 2.5); // output: 1.25
Console.WriteLine(0.1m * 23.4m); // output: 2.34
L’opérateur unaire *
est l’opérateur d’indirection de pointeur.
Opérateur de division /
L’opérateur de division /
divise son opérande de partie gauche par son opérande de partie droite.
Division d'entier
Pour les opérandes des types entiers, le résultat de l’opérateur /
est de type entier et égal au quotient de deux opérandes arrondis vers le zéro :
Console.WriteLine(13 / 5); // output: 2
Console.WriteLine(-13 / 5); // output: -2
Console.WriteLine(13 / -5); // output: -2
Console.WriteLine(-13 / -5); // output: 2
Pour obtenir le quotient de deux opérandes comme un nombre à virgule flottante, utilisez le type float
, double
ou decimal
:
Console.WriteLine(13 / 5.0); // output: 2.6
int a = 13;
int b = 5;
Console.WriteLine((double)a / b); // output: 2.6
Division à virgule flottante
Pour les types float
, double
et decimal
, le résultat de l’opérateur /
est le quotient de deux opérandes :
Console.WriteLine(16.8f / 4.1f); // output: 4.097561
Console.WriteLine(16.8d / 4.1d); // output: 4.09756097560976
Console.WriteLine(16.8m / 4.1m); // output: 4.0975609756097560975609756098
Si l’un des opérandes est decimal
, un autre opérande ne peut être float
ni double
, car ni float
ni double
ne sont implicitement convertibles en decimal
. Vous devez convertir explicitement l’opérande float
ou double
en type decimal
. Pour plus d’informations sur les conversions entre des types numériques, consultez Conversions numériques intégrées.
Opérateur de reste %
L’opérateur restant %
calcule le reste après la division de son opérande de partie gauche par son opérande de partie droite.
Reste entier
Pour les opérandes des types entiers, le résultat de a % b
est la valeur produite par a - (a / b) * b
. Le signe du reste non zéro est le même que celui du signe de l’opérande de partie gauche, comme l’indique l’exemple suivant :
Console.WriteLine(5 % 4); // output: 1
Console.WriteLine(5 % -4); // output: 1
Console.WriteLine(-5 % 4); // output: -1
Console.WriteLine(-5 % -4); // output: -1
Utilisez la méthode Math.DivRem pour calculer à la fois la division entière et les résultats du reste.
Reste à virgule flottante
En ce qui concerne les opérandes float
et double
, le résultat de x % y
pour le x
et le y
finis est la valeur z
afin que
- Le signe de
z
, s’il est différent de zéro, soit identique au signe dex
. - La valeur absolue de
z
soit la valeur produite par|x| - n * |y|
, oùn
représente le plus grand entier possible inférieur ou égal à|x| / |y|
, et où|x|
et|y|
sont les valeurs absolues dex
ety
, respectivement.
Notes
Cette méthode de calcul du reste est analogue à celle utilisée pour les opérandes entiers. Toutefois, elle ne suit pas la spécification IEEE 754. Si l’opération de reste doit être conforme à la spécification IEEE 754, utilisez la méthode Math.IEEERemainder.
Pour plus d’informations sur le comportement de l’opérateur %
avec des opérandes non finis, consultez la section Opérateur de reste dans la Spécification du langage C#.
Pour les opérandes decimal
, l’opérateur de reste %
équivaut à l’opérateur de reste de type System.Decimal.
L’exemple suivant illustre le comportement de l’opérateur de reste pour les opérandes à virgule flottante :
Console.WriteLine(-5.2f % 2.0f); // output: -1.2
Console.WriteLine(5.9 % 3.1); // output: 2.8
Console.WriteLine(5.9m % 3.1m); // output: 2.8
Opérateur d’addition +
L’opérateur d’addition +
calcule la somme de ses opérandes :
Console.WriteLine(5 + 4); // output: 9
Console.WriteLine(5 + 4.3); // output: 9.3
Console.WriteLine(5.1m + 4.2m); // output: 9.3
Vous pouvez également utiliser l’opérateur +
pour la concaténation de chaînes et la combinaison de délégués. Pour plus d’informations, consultez l’article +
et +=
, opérateurs.
Opérateur de soustraction -
L’opérateur de soustraction -
soustrait son opérande de partie droite de son opérande de partie gauche :
Console.WriteLine(47 - 3); // output: 44
Console.WriteLine(5 - 4.3); // output: 0.7
Console.WriteLine(7.5m - 2.3m); // output: 5.2
Vous pouvez également utiliser l’opérateur -
pour la suppression de délégués. Pour plus d’informations, consultez l’article -
et -=
, opérateurs.
Assignation composée
Pour un opérateur binaire op
, une expression d’assignation composée du formulaire
x op= y
équivaut à :
x = x op y
sauf que x
n’est évalué qu’une seule fois.
L’exemple suivant illustre l’utilisation de l’assignation composée avec des opérateurs arithmétiques :
int a = 5;
a += 9;
Console.WriteLine(a); // output: 14
a -= 4;
Console.WriteLine(a); // output: 10
a *= 2;
Console.WriteLine(a); // output: 20
a /= 4;
Console.WriteLine(a); // output: 5
a %= 3;
Console.WriteLine(a); // output: 2
En raison des promotions numériques, le résultat de l’opération op
risque de ne pas être implicitement convertible en type T
de x
. Dans ce cas, si op
est un opérateur prédéfini et que le résultat de l’opération est explicitement convertible en type T
de x
, une expression d’assignation composée de la forme x op= y
équivaut à x = (T)(x op y)
, sauf que x
n’est évalué qu’une seule fois. L’exemple suivant illustre ce comportement :
byte a = 200;
byte b = 100;
var c = a + b;
Console.WriteLine(c.GetType()); // output: System.Int32
Console.WriteLine(c); // output: 300
a += b;
Console.WriteLine(a); // output: 44
Dans l’exemple précédent, la valeur 44
est le résultat de la conversion de la valeur 300
en type byte
.
Notes
Dans le contexte de vérification de dépassement de capacité vérifié, l’exemple précédent lève un OverflowException. Pour plus d’informations, consultez la section Dépassement arithmétique entier.
Vous utilisez également les opérateurs +=
et -=
pour vous abonner d’un événements puis vous désabonner, respectivement. Pour plus d’informations, consultez Guide pratique pour s’abonner et annuler l’abonnement à des événements.
Priorité des opérateurs et associativité
La liste suivante présente les opérateurs arithmétiques de la priorité la plus élevée à la plus basse :
- Opérateurs suffixés d’incrémentation
x++
et de décrémentationx--
- Opérateurs préfixés d’incrémentation
++x
et de décrémentation--x
et opérateurs unaires+
et-
- Opérateurs multiplicatifs
*
,/
et%
- Opérateurs additifs
+
et-
Les opérateurs arithmétiques binaires sont associatifs sur leur gauche. Autrement dit, les opérateurs de même niveau de priorité sont évalués de gauche à droite.
Utilisez des parenthèses, ()
, pour modifier l’ordre d’évaluation imposé par la priorité et l’associativité de l’opérateur.
Console.WriteLine(2 + 2 * 2); // output: 6
Console.WriteLine((2 + 2) * 2); // output: 8
Console.WriteLine(9 / 5 / 2); // output: 0
Console.WriteLine(9 / (5 / 2)); // output: 4
Pour obtenir la liste complète des opérateurs C# classés par niveau de priorité, consultez la section Priorité des opérateurs de l’article Opérateurs C#.
Débordement arithmétique et division par zéro
Quand le résultat d’une opération arithmétique n’est pas compris dans la plage de valeurs finies possibles du type numérique impliqué, le comportement d’un opérateur arithmétique varie selon le type de ses opérandes.
Débordement arithmétique entier
La division d'un entier par zéro lève toujours une exception DivideByZeroException.
Si un dépassement arithmétique entier se produit, un contexte de vérification de débordement, qui peut être vérifié ou non vérifié, contrôle le comportement qui en résulte :
- Dans un contexte vérifié, si le débordement se produit dans une expression constante, une erreur de compilation se produit. Sinon, un OverflowException est levé quand l’opération est effectuée au moment de l’exécution.
- Dans un contexte non vérifié, le résultat est tronqué en supprimant tous les bits de poids fort qui ne tiennent pas dans le type destinataire.
Avec les instructions vérifiées et non vérifiées, vous pouvez utiliser les opérateurs checked
et unchecked
pour contrôler le contexte de vérification de dépassement, dans lequel une expression est évaluée :
int a = int.MaxValue;
int b = 3;
Console.WriteLine(unchecked(a + b)); // output: -2147483646
try
{
int d = checked(a + b);
}
catch(OverflowException)
{
Console.WriteLine($"Overflow occurred when adding {a} to {b}.");
}
Par défaut, les opérations arithmétiques se produisent dans un contexte unchecked.
Débordement arithmétique à virgule flottante
Les opérations arithmétiques avec les types float
et double
ne lèvent jamais d’exceptions. Le résultat des opérations arithmétiques avec ces types peut être une des valeurs spéciales qui représentent l’infini et non un nombre :
double a = 1.0 / 0.0;
Console.WriteLine(a); // output: Infinity
Console.WriteLine(double.IsInfinity(a)); // output: True
Console.WriteLine(double.MaxValue + double.MaxValue); // output: Infinity
double b = 0.0 / 0.0;
Console.WriteLine(b); // output: NaN
Console.WriteLine(double.IsNaN(b)); // output: True
Pour les opérandes du type decimal
, le dépassement arithmétique lève toujours un OverflowException. La division d'un nombre par zéro lève toujours une exception DivideByZeroException.
Erreurs d’arrondi
En raison des limitations générales de la représentation à virgule flottante des nombres réels et de l’arithmétique à virgule flottante, des erreurs d’arrondi peuvent se produire dans les calculs avec les types à virgule flottante. Autrement dit, le résultat d’une expression peut différer du résultat mathématique attendu. L’exemple suivant illustre plusieurs cas de ce genre :
Console.WriteLine(.41f % .2f); // output: 0.00999999
double a = 0.1;
double b = 3 * a;
Console.WriteLine(b == 0.3); // output: False
Console.WriteLine(b - 0.3); // output: 5.55111512312578E-17
decimal c = 1 / 3.0m;
decimal d = 3 * c;
Console.WriteLine(d == 1.0m); // output: False
Console.WriteLine(d); // output: 0.9999999999999999999999999999
Pour plus d’informations, consultez les remarques dans les pages de référence System.Double, System.Single ou System.Decimal.
Capacité de surcharge de l’opérateur
Un type défini par l’utilisateur peut surcharger les opérateurs arithmétiques unaires (++
, --
, +
et -
) et binaires (*
, /
, %
, +
et -
). Quand un opérateur binaire est surchargé, l’opérateur d’assignation composée correspondant est aussi implicitement surchargé. Un type défini par l’utilisateur ne peut pas surcharger explicitement un opérateur d’assignation composée.
Opérateurs vérifiés définis par l’utilisateur
À compter de C# 11, lorsque vous surchargez un opérateur arithmétique, vous pouvez utiliser le mot clé checked
pour définir la version vérifiée de cet opérateur. L’exemple suivant montre comment effectuer cette opération :
public record struct Point(int X, int Y)
{
public static Point operator checked +(Point left, Point right)
{
checked
{
return new Point(left.X + right.X, left.Y + right.Y);
}
}
public static Point operator +(Point left, Point right)
{
return new Point(left.X + right.X, left.Y + right.Y);
}
}
Lorsque vous définissez un opérateur vérifié, vous devez également définir l’opérateur correspondant sans le modificateur checked
. L’opérateur vérifié est appelé dans un contexte vérifié; l’opérateur sans le checked
modificateur est appelé dans un contexte non vérifié. Si vous fournissez uniquement l’opérateur sans le modificateur checked
, il est appelé à la fois dans un contexte checked
et unchecked
.
Lorsque vous définissez les deux versions d’un opérateur, il est attendu que leur comportement diffère uniquement lorsque le résultat d’une opération est trop grand pour être représenté dans le type de résultat comme suit :
- Un opérateur vérifié lève une OverflowException.
- Un opérateur sans modificateur
checked
retourne une instance représentant un résultat tronqué.
Pour plus d’informations sur la différence de comportement des opérateurs arithmétiques intégrés, consultez la section Dépassement arithmétique et division par zéro.
Vous pouvez utiliser le modificateur checked
uniquement lorsque vous surchargez l’un des opérateurs suivants :
- Opérateurs unaires
++
,--
et-
- Opérateurs binaires
*
,/
,+
et-
- Opérateurs de conversion explicite
Notes
Le contexte de contrôle de dépassement dans le corps d’un opérateur vérifié n’est pas affecté par la présence du modificateur checked
. Le contexte par défaut est défini par la valeur de l’option de compilateur CheckForOverflowUnderflow. Utilisez les instructions unchecked
et checked
pour spécifier explicitement le contexte de vérification de dépassement de capacité, comme le montre l’exemple au début de cette section.
spécification du langage C#
Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :
- Opérateurs suffixés d’incrémentation et de décrémentation
- Opérateurs préfixés d’incrémentation et de décrémentation
- Opérateur plus unaire
- Opérateur moins unaire
- Opérateur de multiplication
- Opérateur de division
- Opérateur de reste
- Opérateur d’addition
- Opérateur de soustraction
- Assignation composée
- Opérateurs vérifiés et non vérifiés
- Promotions numériques