Partage via


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 :

Tous les types numériques intégraux et à virgule flottante prennent en charge ces opérateurs.

Les types int, uint, long et ulong définissent tous ces opérateurs. Les autres types intégraux (sbyte, byte, short, ushort, et char) définissent uniquement les opérateurs ++ et --. Pour les autres opérateurs, si vous utilisez les types sbyteintégraux , , shortbyteou ushortchar en tant qu’opérandes, les valeurs sont converties en int type et le type de résultat est int. Si les opérandes sont différents types intégraux ou à virgule flottante, leurs valeurs sont converties en type contenant le plus proche, si un tel type existe. 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.

La documentation de référence du langage C# décrit la version la plus récente du langage C#. Il contient également la documentation initiale des fonctionnalités dans les préversions publiques pour la prochaine version du langage.

La documentation identifie toute fonctionnalité introduite en premier dans les trois dernières versions de la langue ou dans les préversions publiques actuelles.

Conseil / Astuce

Pour savoir quand une fonctionnalité a été introduite en C#, consultez l’article sur l’historique des versions du langage C#.

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 xavant 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 xaprè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 disponible sous deux formes : l’opérateur de décrémentation postfix, x--et l’opérateur de décrémentation de préfixe, --x.

Opérateur de décrémentation suffixé

Le résultat de x-- est la valeur de xavant 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 xaprè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 de types entiers, le résultat de l’opérateur / est d’un type entier et est égal au quotient des deux opérandes arrondis à 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 des deux opérandes en tant que nombre à virgule flottante, utilisez le ou doubledecimal le floattype :

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 le float, doubleet decimal les types, l’opérateur / retourne le quotient des 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 un opérande est decimal, l’autre opérande ne peut pas être float ou double, car ni ni double n’a float une conversion implicite 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 de types entiers, le résultat a % b est la valeur produite par $a - \frac{a}{b} \times b$. Le signe du reste non zéro correspond au signe de l’opérande de gauche, comme l’illustre 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 , s’il n’est zpas égal à zéro, correspond au signe de x.
  • La valeur z absolue provient du calcul $|x| - n \times |y|$, où n est le plus grand entier inférieur ou égal à $\frac{|x|}{|y|}$. Ici, $|x|$ et $|y|$ représentent les valeurs absolues et xy, respectivement.

Notes

Cette méthode de calcul du reste est similaire à la méthode utilisée pour les opérandes entiers, mais elle diffère de 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 decimal les opérandes, l’opérateur % de reste fonctionne de la même façon que l’opérateur restant du System.Decimal type.

L’exemple suivant montre comment l’opérateur restant se comporte avec des 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 l’opérande de droite de l’opérande de 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 supprimer un délégué. Pour plus d’informations, consultez les opérateurs et -= les- 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 est évalué 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 de promotions numériques, le résultat de l’opération op peut 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 trie les opérateurs arithmétiques de la priorité la plus élevée vers la priorité la plus basse :

  • Opérateurs suffixés d’incrémentation x++ et de décrémentation x--
  • Opérateurs d’incrémentation ++x et de décrémentation --x de préfixe, et unaire + et - opérateurs
  • Opérateurs multiplicatifs *, / et %
  • Opérateurs additifs + et -

Les opérateurs arithmétiques binaires sont associatifs sur leur gauche. Autrement dit, le compilateur évalue les opérateurs ayant le même niveau de priorité 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.

Notes

La division d’entiers a un cas particulier dans lequel une ArithmeticException exception peut être levée même dans un contexte non vérifié. Lorsque l’opérande gauche est la valeur minimale d’un type entier signé (int.MinValue ou long.MinValue) et que l’opérande droit est -1, le résultat ne peut pas être représenté dans le type de destination. Le runtime .NET lève une ArithmeticException exception dans ce cas, comme illustré dans l’exemple suivant :

int a = int.MinValue;
int b = -1;
try
{
    int c = unchecked(a / b);
}
catch (ArithmeticException)
{
    Console.WriteLine($"Overflow occurred when dividing {a} by {b}.");
}

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 à l’aide des float types et double ne lèvent jamais d’exception. Le résultat des opérations arithmétiques à l’aide de ces types peut être l’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 de limitations générales dans la représentation à virgule flottante des nombres réels et des erreurs arithmétiques à virgule flottante, des erreurs d’arrondi peuvent se produire dans les calculs qui utilisent des types à virgule flottante. 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 sur les pages de référence System.Double, System.Single ou System.Decimal .

Capacité de surcharge de l’opérateur

Vous pouvez surcharger les opérateurs arithmétiques unaires (++, --, +, et ) et -binaires (*, /, %+, et -) pour un type défini par l’utilisateur. Lorsque vous surchargez un opérateur binaire, vous surchargez implicitement l’opérateur d’affectation composée correspondante. À compter de C# 14, un type défini par l’utilisateur peut surcharger explicitement les opérateurs d’affectation composée (op=) pour fournir une implémentation plus efficace. En règle générale, un type surcharge ces opérateurs, car la valeur peut être mise à jour en place, plutôt que d’allouer une nouvelle instance pour stocker le résultat de l’opération. Si un type ne fournit pas de surcharge explicite, le compilateur génère la surcharge implicite.

Opérateurs vérifiés définis par l’utilisateur

Lorsque vous surchargez un opérateur arithmétique, vous pouvez utiliser le checked mot clé 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. Un contexte vérifié appelle l’opérateur vérifié et un contexte non vérifié appelle l’opérateur sans le checked modificateur.

Lorsque vous définissez les deux versions d’un opérateur, leur comportement diffère uniquement lorsque le résultat d’une opération est trop volumineux pour représenter 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 -
  • Affectation composée *=, /=, +=, et opérateurs -= (C# 14 et versions ultérieures)
  • Opérateurs de conversion explicite

Notes

Le checked modificateur n’affecte pas le contexte de contrôle de dépassement de capacité dans son corps. Le contexte par défaut est défini par la valeur de l’option de compilateur CheckForOverflowUnderflow. Utilisez les instructions checkedet unchecked 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# :

Voir aussi