Aritmetiska operatorer (C#-referens)

Följande operatorer utför aritmetiska åtgärder med operander av numeriska typer:

Dessa operatorer stöds av alla numeriska typer av integrerad och flyttal .

När det gäller integraltyper definieras dessa operatorer (förutom operatorerna ++ och -- ) för typerna int, uint, longoch ulong . När operander är av andra integraltyper (sbyte, , shortbyte, ushorteller char), konverteras deras värden till int typen, vilket också är resultattypen för en åtgärd. När operander har olika typer av integraler eller flyttal konverteras deras värden till den närmaste innehållande typen, om en sådan typ finns. Mer information finns i avsnittet Numeriska kampanjer i C#-språkspecifikationen. Operatorerna ++ och -- definieras för alla numeriska typer av integraler och flyttalstyper och teckentypen . Resultattypen för ett sammansatt tilldelningsuttryck är typen av den vänstra operanden.

Inkrementsoperator ++

Den oföränderliga inkrementsoperatorn ++ ökar sin operande med 1. Operand måste vara en variabel, en egenskapsåtkomst eller en indexerare .

Inkrementsoperatorn stöds i två former: postfix-inkrementsoperatorn , x++och prefixet increment operator, ++x.

Postfix-inkrementsoperator

Resultatet av x++ är värdet xför före åtgärden, som följande exempel visar:

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

Inkrementsoperator för prefix

Resultatet av ++x är värdet xför efter åtgärden, som följande exempel visar:

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

Decrement-operatorn --

Den unary decrementoperatorn -- decrements dess operand vid 1. Operand måste vara en variabel, en egenskapsåtkomst eller en indexerare .

Decrementoperatorn stöds i två former: postfixdeprevalensoperatorn , x--och prefixets decrementoperator, --x.

Postfix-decrementoperator

Resultatet av x-- är värdet xför före åtgärden, som följande exempel visar:

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

Prefixdeprevalensoperator

Resultatet av --x är värdet xför efter åtgärden, som följande exempel visar:

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

Unary plus- och minusoperatorer

Den unary + operatorn returnerar värdet för dess operand. Den unary - operatorn beräknar den numeriska negationen av dess operand.

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

Typen ulong stöder inte unary-operatorn - .

Multiplikationsoperator *

Multiplikationsoperatorn * beräknar produkten av sina operander:

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

Unary-operatorn * är pekarens indirekta operator.

Divisionsoperator/

Divisionsoperatorn / delar sin vänstra operande med sin högra operande.

Heltalsdivision

För operander av heltalstyper är resultatet av operatorn / av heltalstyp och är lika med kvoten för de två operanderna avrundade mot noll:

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

Om du vill hämta kvoten för de två operanderna som ett flyttalsnummer använder du floattypen , doubleeller decimal :

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

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

Flyttalsdelning

För typerna float, doubleoch decimal är resultatet av operatorn / kvoten för de två operanderna:

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

Om en av operanderna är decimalkan en annan operande varken float vara eller double, eftersom varken float eller double implicit kan konverteras till decimal. Du måste uttryckligen float konvertera eller double operand till decimal typen . Mer information om konverteringar mellan numeriska typer finns i Inbyggda numeriska konverteringar.

Restoperator %

Restoperatorn % beräknar resten efter att ha delat sin vänstra operande med sin högra operande.

Heltalsrester

För operander av heltalstyper är resultatet av a % b värdet som genereras av a - (a / b) * b. Tecknet för resten som inte är noll är detsamma som tecknet för den vänstra operanden, som följande exempel visar:

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

Math.DivRem Använd metoden för att beräkna både heltalsdivision och restresultat.

Flyttalsrester

float För operanderna och double är resultatet av x % y för det ändliga x och y det värde z som

  • Tecknet för z, om det inte är noll, är samma som tecknet för x.
  • Det absoluta värdet z för är det värde som genereras av |x| - n * |y| var n är det största möjliga heltalet som är mindre än eller lika med |x| / |y| och |x| och |y| är de absoluta värdena x för respektive y.

Kommentar

Den här metoden för beräkning av resten motsvarar den som används för heltalsoperor, men skiljer sig från IEEE 754-specifikationen. Om du behöver reståtgärden som uppfyller IEEE 754-specifikationen Math.IEEERemainder använder du metoden.

Information om beteendet för operatorn % med icke-ändliga operander finns i avsnittet Restoperator i C#-språkspecifikationen.

decimal För operanderna motsvarar restoperatorn % resten av System.Decimal typens operator.

I följande exempel visas beteendet för restoperatorn med flyttalsoperatorer:

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 +

Additionsoperatorn + beräknar summan av sina operander:

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

Du kan också använda operatorn + för kombination av strängsammanfogning och ombud. Mer information finns i artikeln operatorer + och .+=

Subtraktionsoperator –

Subtraktionsoperatorn - subtraherar sin högra operande från sin vänstra operande:

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

Du kan också använda operatorn för borttagning av - ombud. Mer information finns i artikeln operatorer - och .-=

Sammansatt tilldelning

För en binär operator op, ett sammansatt tilldelningsuttryck för formuläret

x op= y

motsvarar

x = x op y

förutom att x endast utvärderas en gång.

I följande exempel visas användningen av sammansatt tilldelning med aritmetiska operatorer:

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

På grund av numeriska kampanjer kanske resultatet av op åtgärden inte implicit kan konverteras till typen Tx. I ett sådant fall, om op är en fördefinierad operator och resultatet av åtgärden uttryckligen kan konverteras till typen T av x, är ett sammansatt tilldelningsuttryck av formuläret x op= y likvärdigt med x = (T)(x op y), förutom att endast x utvärderas en gång. Följande exempel visar det beteendet:

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

I föregående exempel är värdet 44 resultatet av att konvertera värdet 300 till byte typen.

Kommentar

I den markerade överflödeskontrollkontexten genererar föregående exempel en OverflowException. Mer information finns i avsnittet Heltalsaritmiskt spill .

Du använder också operatorerna += och -= för att prenumerera på och avbryta prenumerationen på en händelse. Mer information finns i Så här prenumererar du på och avbryter prenumerationen på händelser.

Operatorprioritet och associativitet

Följande lista beställer aritmetiska operatorer med början från den högsta prioriteten till den lägsta:

  • Operatorer för inkrement x++ och minskning av x-- postfix
  • Inkrement ++x och dementering --x av prefix samt unary + och - operatorer
  • Multiplicativa *operatorer , /och %
  • Additiva + och - operatorer

Binära aritmetiska operatorer är vänster-associativa. Operatorer med samma prioritetsnivå utvärderas från vänster till höger.

Använd parenteser, (), för att ändra ordningen på utvärderingen som har införts av operatorprioritet och associativitet.

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

En fullständig lista över C#-operatorer ordnade efter prioritetsnivå finns i avsnittet Operatorprioriteten i artikeln C#-operatorer .

Aritmetiskt spill och division med noll

När resultatet av en aritmetikåtgärd ligger utanför intervallet för möjliga ändliga värden av den berörda numeriska typen beror beteendet för en aritmetikoperator på typen av dess operander.

Heltalsaritmetiskt spill

Heltalsdivision med noll genererar alltid en DivideByZeroException.

Om heltals-aritmetiskt spill inträffar styr överflödeskontrollkontexten, som kan kontrolleras eller avmarkeras, det resulterande beteendet:

  • I en markerad kontext uppstår ett kompileringsfel om spill inträffar i ett konstant uttryck. Annars genereras en OverflowException när åtgärden utförs vid körning.
  • I en omarkerad kontext trunkeras resultatet genom att alla bitar i hög ordning som inte får plats i måltypen ignoreras.

Tillsammans med de markerade och omarkerade uttrycken kan du använda operatorerna checked och unchecked för att styra överflödeskontrollkontexten, där ett uttryck utvärderas:

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

Som standard utförs aritmetiska åtgärder i en omarkerad kontext.

Flyttalsaritmetiskt spill

Aritmetiska åtgärder med typerna float och double utlöser aldrig ett undantag. Resultatet av aritmetiska åtgärder med dessa typer kan vara ett av specialvärden som representerar oändligheten och inte ett tal:

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 typens operander decimal genererar aritmetiskt spill alltid ett OverflowException. Division med noll genererar alltid en DivideByZeroException.

Avrundningsfel

På grund av allmänna begränsningar i flyttalsrepresentationen av verkliga tal och flyttalsaritmetik kan avrundningsfel inträffa i beräkningar med flyttalstyper. Det innebär att det producerade resultatet av ett uttryck kan skilja sig från det förväntade matematiska resultatet. I följande exempel visas flera sådana fall:

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

Mer information finns i kommentarer på referenssidorna System.Double, System.Single eller System.Decimal .

Överlagring av operator

En användardefinierad typ kan överbelasta de oföränderliga (++, , --+och -) och binära (*, , %/, +och -) aritmetiska operatorerna. När en binär operator är överbelastad överbelastas även motsvarande sammansatta tilldelningsoperator implicit. En användardefinierad typ kan inte uttryckligen överbelasta en sammansatt tilldelningsoperator.

Användardefinierade kontrollerade operatorer

Från och med C# 11 kan du använda nyckelordet checked för att definiera den kontrollerade versionen av operatorn när du överbelastar en aritmetikoperator. I följande exempel visas hur du gör det:

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

När du definierar en kontrollerad operator måste du också definiera motsvarande operator utan checked modifieraren. Den kontrollerade operatorn anropas i en kontrollerad kontext. Operatorn utan checked modifieraren anropas i en omarkerad kontext. Om du bara anger operatorn utan checked modifieraren anropas den i både en checked och unchecked kontext.

När du definierar båda versionerna av en operator förväntas deras beteende bara skilja sig när resultatet av en åtgärd är för stort för att representera i resultattypen enligt följande:

  • En kontrollerad operator genererar en OverflowException.
  • En operator utan checked modifieraren returnerar en instans som representerar ett trunkerat resultat.

Information om skillnaden i beteende för de inbyggda aritmetiska operatorerna finns i avsnittet Aritmetiskt spill och division efter noll .

Du kan bara använda checked modifieraren när du överbelastar någon av följande operatorer:

Kommentar

Överflödeskontrollkontexten i en kontrollerad operators brödtext påverkas inte av förekomsten av checked modifieraren. Standardkontexten definieras av värdet för kompileringsalternativet CheckForOverflowUnderflow . checked Använd -instruktionerna och unchecked för att uttryckligen ange kontexten för spillkontroll, som exemplet i början av det här avsnittet visar.

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Se även