Freigeben über


Arithmetische Operatoren (C#-Referenz)

Die folgenden Operatoren führen arithmetische Operationen mit Operanden des numerischen Typs aus:

Alle integralen und gleitkommabezogenen numerischen Typen unterstützen diese Operatoren.

Die int, uint, long, und ulong Typen definieren alle diese Operatoren. Die anderen integralen Typen (sbyte, byte, short, ushort, und char) definieren nur die ++ und -- Operatoren. Wenn Sie für die anderen Operatoren die integralen Typen sbyte, byte, , short, ushort, oder char als Operanden verwenden, werden die Werte in den int Typ konvertiert, und der Ergebnistyp lautet int. Wenn die Operanden unterschiedliche integrale oder Gleitkommatypen sind, werden ihre Werte in den nächstgelegenen enthaltenden Typ konvertiert, wenn ein solcher Typ vorhanden ist. Weitere Informationen finden Sie im Abschnitt Numerische Heraufstufungen der Spezifikation für die Sprache C#. Die ++- und ---Operatoren werden für alle numerischen integralen und Gleitkommatypen sowie den char-Typ definiert. Der Ergebnistyp eines zusammengesetzten Zuweisungsausdrucks ist der Typ des linken Operanden.

Die C#-Sprachreferenz dokumentiert die zuletzt veröffentlichte Version der C#-Sprache. Außerdem enthält sie eine erste Dokumentation zu Funktionen in der öffentlichen Vorschau für die kommende Sprachversion.

In der Dokumentation werden alle Features identifiziert, die in den letzten drei Versionen der Sprache oder in der aktuellen öffentlichen Vorschau eingeführt wurden.

Tipp

Informationen dazu, wann ein Feature erstmals in C# eingeführt wurde, finden Sie im Artikel zum Versionsverlauf der C#-Sprache.

Inkrementoperator ++

Der unäre Inkrementoperator (++) erhöht seinen Operanden um 1. Der Operand muss eine Variable, ein Eigenschaftenzugriff oder ein Indexerzugriff sein.

Der Inkrementoperator wird in zwei Formen unterstützt: als Postfix-Inkrementoperator x++ und als Präfix-Inkrementoperator ++x.

Postfix-Operator für Inkrement

Das Ergebnis von x++ ist der Wert von xvor dem Vorgang, wie das folgende Beispiel zeigt:

int i = 3;
Console.WriteLine(i);   // output: 3
Console.WriteLine(i++); // output: 3
Console.WriteLine(i);   // output: 4

Präfixinkrement-Operator

Das Ergebnis von ++x ist der Wert von xnach dem Vorgang, wie das folgende Beispiel zeigt:

double a = 1.5;
Console.WriteLine(a);   // output: 1.5
Console.WriteLine(++a); // output: 2.5
Console.WriteLine(a);   // output: 2.5

Dekrementoperator --

Der unäre Dekrementoperator -- verringert seinen Operanden um 1. Der Operand muss eine Variable, ein Eigenschaftenzugriff oder ein Indexerzugriff sein.

Der Operator für die Dekrementierung ist in zwei Formen verfügbar: der Postfix-Dekrementoperator und x--der Präfix-Dekrementoperator. --x

Postfix-Operator für Dekrement

Das Ergebnis von x-- ist der Wert von xvor dem Vorgang, wie das folgende Beispiel zeigt:

int i = 3;
Console.WriteLine(i);   // output: 3
Console.WriteLine(i--); // output: 3
Console.WriteLine(i);   // output: 2

Präfix-Dekrementoperator

Das Ergebnis von --x ist der Wert von xnach dem Vorgang, wie das folgende Beispiel zeigt:

double a = 1.5;
Console.WriteLine(a);   // output: 1.5
Console.WriteLine(--a); // output: 0.5
Console.WriteLine(a);   // output: 0.5

Unäre Plus- und Minusoperatoren

Der unäre +-Operator gibt den Wert seines Operanden zurück. Der unäre --Operator berechnet die numerische Negation des Operanden.

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

Der ulong-Typ unterstützt den unären --Operator nicht.

Multiplikationsoperator *

Der Multiplikationsoperator * berechnet das Produkt seiner Operanden:

Console.WriteLine(5 * 2);         // output: 10
Console.WriteLine(0.5 * 2.5);     // output: 1.25
Console.WriteLine(0.1m * 23.4m);  // output: 2.34

Der unäre *-Operator ist der Zeigerdereferenzierungsoperator.

Divisionsoperator /

Der Divisionsoperator / dividiert den linken Operanden durch den rechten Operanden.

Ganzzahldivision

Für die Operanden von ganzzahligen Typen ist das Ergebnis des / Operators ein ganzzahliger Typ und entspricht dem Quotient der beiden Operanden, die auf Null gerundet sind:

Console.WriteLine(13 / 5);    // output: 2
Console.WriteLine(-13 / 5);   // output: -2
Console.WriteLine(13 / -5);   // output: -2
Console.WriteLine(-13 / -5);  // output: 2

Wenn Sie den Quotient der beiden Operanden als Gleitkommazahl abrufen möchten, verwenden Sie folgendesfloatdouble, oder decimal geben Sie Folgendes ein:

Console.WriteLine(13 / 5.0);       // output: 2.6

int a = 13;
int b = 5;
Console.WriteLine((double)a / b);  // output: 2.6

Gleitkommadivision

Für die float, doubleund decimal typen gibt der / Operator den Quotient der beiden Operanden zurück:

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

Wenn es sich um einen Operanden handeltdecimal, kann der andere Operand nicht sein float oder double, da weder doublefloat eine implizite Konvertierung vorhanden decimalist. Sie müssen den Operanden float oder double explizit zum Typ decimal konvertieren. Weitere Informationen zu Konvertierungen zwischen numerischen Typen finden Sie unter Built-in numeric conversions (Integrierte numerischer Konvertierungen).

Restoperator %

Der Restoperator % berechnet den Rest nach der Division seines linken Operanden durch den rechten Operanden.

Ganzzahliger Rest

Bei Operanden ganzzahliger Typen ist das Ergebnis a % b der von $a - \frac{a}{b} \times b$erzeugten Wert. Das Zeichen des Nicht-Null-Rests entspricht dem Zeichen des linken Operanden, wie das folgende Beispiel zeigt:

Console.WriteLine(5 % 4);   // output: 1
Console.WriteLine(5 % -4);  // output: 1
Console.WriteLine(-5 % 4);  // output: -1
Console.WriteLine(-5 % -4); // output: -1

Verwenden Sie die Math.DivRem-Methode, wenn Sie sowohl Ganzzahldivision als auch Restergebnisse berechnen möchten.

Gleitkommarest

Für die Operanden float und double entspricht das Ergebnis von x % y für die endlichen Werte x und y dem Wert z, sodass:

  • Das Zeichen von z, wenn ungleich Null, entspricht dem Vorzeichen von x.
  • Der absolute Wert z stammt aus der Berechnung $|x| - n \times |y|$, wobei n die größte ganze Zahl kleiner oder gleich $\frac{|x|} ist.{|y|}$. Hier stellen $|x|$ und $|y|$ die absoluten Werte bzw xy. die Absolutwerte dar.

Hinweis

Diese Methode zum Berechnen des Rests ähnelt der Methode, die für ganzzahlige Operanden verwendet wird, unterscheidet sich jedoch von der IEEE 754-Spezifikation. Wenn Sie den Restvorgang benötigen, der der IEEE 754-Spezifikation entspricht, verwenden Sie die Methode Math.IEEERemainder.

Weitere Informationen zum Verhalten des %-Operators bei nicht begrenzten Operanden finden Sie im Abschnitt Restoperator der C#-Sprachspezifikation.

Bei decimal Operanden funktioniert der Restoperator % mit dem Restoperator des System.Decimal Typs.

Das folgende Beispiel zeigt, wie sich der Restoperator mit Gleitkommaopernden verhält:

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

Additionsoperator +

Der Additionsoperator + berechnet die Summe der Operanden:

Console.WriteLine(5 + 4);       // output: 9
Console.WriteLine(5 + 4.3);     // output: 9.3
Console.WriteLine(5.1m + 4.2m); // output: 9.3

Der +-Operator kann auch für die Zeichenfolgenverkettung und Delegatkombination verwendet werden. Weitere Informationen finden Sie im Artikel zu den Operatoren + und +=.

Subtraktionsoperator -

Der Subtraktionsoperator - subtrahiert den rechten Operanden vom linken Operanden:

Console.WriteLine(47 - 3);      // output: 44
Console.WriteLine(5 - 4.3);     // output: 0.7
Console.WriteLine(7.5m - 2.3m); // output: 5.2

Sie können den - Operator auch verwenden, um eine Stellvertretung zu entfernen. Weitere Informationen finden Sie unter den Operatoren und -= den- Operatoren.

Verbundzuweisung

Bei einem binären Operator op entspricht ein Verbundzuweisungsausdruck der Form

x op= y

Ist äquivalent zu

x = x op y

Mit der Ausnahme, dass x nur einmal ausgewertet wird.

Im folgenden Beispiel wird die Verwendung von Verbundzuweisungen mit arithmetischen Operatoren veranschaulicht:

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

Aufgrund numerischer Werbung kann das Ergebnis des op Vorgangs möglicherweise nicht implizit in den Typ T von x. In diesem Fall gilt Folgendes: Wenn op ein vordefinierter Operator ist und das Ergebnis der Operation explizit in den Typ T von x konvertiert werden kann, entspricht ein Verbundzuweisungsausdruck der Form x op= y dem Ausdruck x = (T)(x op y). Der einzige Unterschied ist, dass x nur einmal ausgewertet wird. Das folgende Beispiel veranschaulicht dieses Verhalten:

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

Im vorherigen Beispiel ist der Wert 44 das Ergebnis der Konvertierung des Werts 300 in den byte-Typ.

Hinweis

Im überprüften Überlaufüberprüfungskontext löst das vorherige Beispiel eine OverflowException aus. Weitere Informationen finden Sie im Abschnitt Überlauf der Integerarithmetik.

Die Operatoren += und -= können auch zum Abonnieren von Ereignissen und zum Kündigen eines Ereignisabonnements verwendet werden. Weitere Informationen finden Sie unter Abonnieren von Ereignissen und Kündigen von Ereignisabonnements.

Operatorrangfolge und Assoziativität

In der folgenden Liste werden arithmetische Operatoren von der höchsten Rangfolge bis zur niedrigsten Rangfolge sortiert:

  • Postfixinkrementoperator x++ und Postfixdekrementoperator x--
  • Präfixinkrementierungs- und Dekrementierungsoperatoren ++x--x sowie unär + und - operatoren
  • Multiplikative Operatoren *, / und %
  • Additive Operatoren + und -

Binäre arithmetische Operatoren sind linksassoziativ. Das heißt, der Compiler wertet Operatoren mit derselben Rangfolgeebene von links nach rechts aus.

Verwenden Sie Klammern (), wenn Sie die Reihenfolge der Auswertung ändern möchten, die durch Operatorrangfolge und Assoziativität festgelegt wird.

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

Die vollständige Liste der nach Rangfolgenebene sortierten C#-Operatoren finden Sie im Abschnitt Operatorrangfolge im Artikel C#-Operatoren.

Arithmetischer Überlauf und Division durch 0 (null)

Liegt das Ergebnis einer arithmetischen Operation außerhalb des Bereichs möglicher endlicher Werte des betreffenden numerischen Typs, hängt das Verhalten eines arithmetischen Operators vom Typ der Operanden ab.

Arithmetischer Überlauf bei ganzen Zahlen

Division ganzer Zahlen durch Null löst immer eine DivideByZeroException aus.

Im Fall eines arithmetischen Überlaufs bei ganzen Zahlen steuert der Kontext für Überlaufprüfungen, der checked oder unchecked sein kann, das sich ergebende Verhalten:

  • In einem aktivierten Kontext tritt bei einem Überlauf in einem konstanten Ausdruck ein Kompilierzeitfehler auf. Andernfalls wird, wenn die Operation zur Laufzeit ausgeführt wird, eine OverflowException-Ausnahme ausgelöst.
  • In einem deaktivierten Kontext wird das Ergebnis gekürzt, indem alle höherwertigen Bits verworfen werden, die nicht in den Zieltyp passen.

Hinweis

Die ganzzahlige Division weist einen Sonderfall auf, in dem eine ArithmeticException Option auch in einem nicht aktivierten Kontext ausgelöst werden kann. Wenn der linke Operand der Minimalwert eines signierten ganzzahligen Typs (int.MinValue oder long.MinValue) ist und der rechte Operand ist -1, kann das Ergebnis nicht im Zieltyp dargestellt werden. Die .NET-Laufzeit löst eine in diesem Fall aus ArithmeticException , wie im folgenden Beispiel gezeigt:

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

Neben den Anweisungen checked und unchecked können Sie mit den checked- und unchecked-Operatoren den Kontext für Überlaufprüfungen steuern, in dem ein Ausdruck ausgewertet wird:

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}.");
}

Standardmäßig erscheinen arithmetische Operationen in einem unchecked-Kontext.

Arithmetischer Überlauf bei Gleitkommatypen

Arithmetische Vorgänge mit den float Und-Typen double lösen niemals eine Ausnahme aus. Das Ergebnis arithmetischer Vorgänge, die diese Typen verwenden, kann einer der speziellen Werte sein, die unendliche und keine Zahl darstellen:

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

Für Operanden vom Typ decimal löst ein arithmetischer Überlauf immer eine OverflowException-Ausnahme aus. Eine Division durch Null löst immer eine DivideByZeroException aus.

Rundungsfehler

Aufgrund allgemeiner Einschränkungen bei der Gleitkommadarstellung realer Zahlen und Gleitkommaarithmetik können Abrundenfehler in Berechnungen auftreten, die Gleitkommatypen verwenden. Das Ergebnis eines Ausdrucks kann sich von dem erwarteten mathematischen Ergebnis unterscheiden. Im folgenden Beispiel werden einige solcher Fälle dargestellt:

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

Weitere Informationen finden Sie in den Hinweisen auf den Referenzseiten "System.Double", " System.Single" oder " System.Decimal ".

Operatorüberladbarkeit

Sie können die unären (++, --, +, und -) und binären Operatoren (*, /, %+und -) arithmetischen Operatoren für einen benutzerdefinierten Typ überladen. Wenn Sie einen binären Operator überladen, überladen Sie auch implizit den entsprechenden zusammengesetzten Zuordnungsoperator. Ab C# 14 kann ein benutzerdefinierter Typ die zusammengesetzten Zuordnungsoperatoren (op=) explizit überladen, um eine effizientere Implementierung bereitzustellen. In der Regel überlastet ein Typ diese Operatoren, da der Wert direkt aktualisiert werden kann, anstatt eine neue Instanz zuzuweisen, um das Ergebnis des Vorgangs zu speichern. Wenn ein Typ keine explizite Überladung bereitstellt, generiert der Compiler die implizite Überladung.

Benutzerdefinierte checked-Operatoren

Wenn Sie einen arithmetischen Operator überladen, können Sie das checked Schlüsselwort verwenden, um die überprüfte Version dieses Operators zu definieren. Das folgende Beispiel zeigt, wie Sie dabei vorgehen müssen:

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);
    }
}

Wenn Sie einen checked-Operator definieren, müssen Sie auch den entsprechenden Operator ohne den checked-Modifizierer definieren. Ein aktivierter Kontext ruft den aktivierten Operator auf, und ein deaktivierter Kontext ruft den Operator ohne checked Modifizierer auf.

Wenn Sie beide Versionen eines Operators definieren, unterscheidet sich ihr Verhalten nur, wenn das Ergebnis eines Vorgangs zu groß ist, um den Ergebnistyp wie folgt darzustellen:

  • Ein checked-Operator löst eine OverflowException aus.
  • Ein Operator ohne den checked-Modifizierer gibt eine Instanz zurück, die ein gekürztes Ergebnis darstellt.

Informationen zum unterschiedlichen Verhalten der integrierten arithmetischen Operatoren finden Sie im Abschnitt Arithmetischer Überlauf und Division durch 0 (null).

Sie können den checked-Modifizierer nur verwenden, wenn Sie einen der folgenden Operatoren überladen:

  • Unäre ++-, --- und --Operatoren
  • Binäre *-, /-, +- und --Operatoren
  • Zusammengesetzte Zuweisung *=, /=, += und -= Operatoren (C# 14 und höher)
  • Explizite Konvertierungsoperatoren

Hinweis

Der checked Modifizierer wirkt sich nicht auf den Überlaufüberprüfungskontext innerhalb des Textkörpers aus. Der Standardkontext wird durch den Wert der CheckForOverflowUnderflow-Compileroption definiert. Verwenden Sie die checked- und unchecked-Anweisungen, um den Kontext für Überlaufüberprüfungen explizit anzugeben, wie das Beispiel am Anfang dieses Abschnitts veranschaulicht.

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Weitere Informationen