Partilhar via


Operadores aritméticos (referência C#)

Os operadores a seguir executam operações aritméticas com operandos de tipos numéricos:

Esses operadores são suportados por todos os tipos numéricos integrais e de vírgula flutuante.

No caso de tipos integrais, esses operadores (exceto os ++ e -- operadores) são definidos para os inttipos , uint, long, e ulong . Quando os operandos são de outros tipos integrais (, , , ushort, ou char), seus valores são convertidos para o int tipo, que também é o tipo de resultado de uma shortoperação. bytesbyte Quando os operandos são de diferentes tipos integrais ou de vírgula flutuante, seus valores são convertidos para o tipo de contenção mais próximo, se tal tipo existir. Para obter mais informações, consulte a seção Promoções numéricas da especificação da linguagem C#. Os ++ operadores e -- são definidos para todos os tipos numéricos integrais e de vírgula flutuante e o tipo char . O tipo de resultado de uma expressão de atribuição composta é o tipo do operando esquerdo.

Operador de incremento ++

O operador ++ de incremento unário incrementa seu operando em 1. O operando deve ser uma variável, um acesso de propriedade ou um acesso de indexador .

O operador de incremento é suportado de duas formas: o operador de incremento postfix, x++e o operador de incremento de prefixo, ++x.

Operador de incremento Postfix

O resultado de é o valor de antes da x operação, como mostra o exemplo a x++ seguir:

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

Operador de incremento de prefixo

O resultado de ++x é o valor de após a operação, como mostra o exemplo a x seguir:

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

Operador de decréscimo --

O operador -- de decréscimo unário diminui seu operando em 1. O operando deve ser uma variável, um acesso de propriedade ou um acesso de indexador .

O operador de decréscimo é suportado de duas formas: o operador de decréscimo postfix, x--e o operador de decréscimo prefixo, --x.

Operador de decréscimo Postfix

O resultado de é o valor de antes da x operação, como mostra o exemplo a x-- seguir:

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

Operador de decréscimo de prefixo

O resultado de --x é o valor de após a operação, como mostra o exemplo a x seguir:

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

Unary mais e menos operadores

O operador unário + retorna o valor de seu operando. O operador unário - calcula a negação numérica de seu operando.

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

O tipo ulong não suporta o operador unário - .

Operador de multiplicação *

O operador * de multiplicação calcula o produto de seus operandos:

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

O operador unário * é o operador indirection do ponteiro.

Operador de divisão /

O operador / de divisão divide seu operando esquerdo pelo operando direito.

Divisão inteira

Para os operandos de tipos inteiros, o / resultado do operador é de um tipo inteiro e é igual ao quociente dos dois operandos arredondados para zero:

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

Para obter o quociente dos dois operandos como um número de vírgula flutuante, use o float, doubleou decimal digite:

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

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

Divisão de vírgula flutuante

Para o float, doublee decimal tipos, o resultado do operador é o / quociente dos dois operandos:

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

Se um dos operandos é decimal, outro operando não pode ser nem float , doubleporque nem float nem double é implicitamente conversível em decimal. Você deve converter explicitamente o float operando ou double para o decimal tipo. Para obter mais informações sobre conversões entre tipos numéricos, consulte Conversões numéricas internas.

Operador remanescente %

O operador % restante calcula o restante depois de dividir seu operando esquerdo por seu operando direito.

Inteiro restante

Para os operandos de tipos inteiros, o resultado de a % b é o valor produzido por a - (a / b) * b. O sinal do restante diferente de zero é o mesmo que o sinal do operando esquerdo, como mostra o exemplo a seguir:

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

Use o método para calcular a divisão inteira e os Math.DivRem resultados restantes.

Remanescente de vírgula flutuante

Para os float e double operandos, o resultado de x % y para o finito x e y é o valor z tal que

  • O sinal de , se diferente de zzero, é o mesmo que o sinal de x.
  • O valor absoluto de z é o valor produzido por |x| - n * |y| onde n é o maior inteiro possível que é menor ou igual a |x| / |y| e |x| e |y| são os valores absolutos de x e y, respectivamente.

Nota

Este método de cálculo do restante é análogo ao usado para operandos inteiros, mas diferente da especificação IEEE 754. Se você precisar da operação restante que esteja em conformidade com a especificação IEEE 754, use o Math.IEEERemainder método.

Para obter informações sobre o % comportamento do operador com operandos não finitos, consulte a seção Operador restante da especificação da linguagem C#.

Para os decimal operandos, o operador % restante é equivalente ao operador restante do System.Decimal tipo.

O exemplo a seguir demonstra o comportamento do operador restante com operandos de ponto flutuante:

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

Operador de adição +

O operador + de adição calcula a soma de seus operandos:

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

Você também pode usar o + operador para concatenação de cadeia de caracteres e combinação de delegação. Para obter mais informações, consulte o + artigo e += operadores .

Operador de subtração -

O operador - de subtração subtrai seu operando direito do operando esquerdo:

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

Você também pode usar o - operador para remoção de delegado. Para obter mais informações, consulte o - artigo e -= operadores .

Atribuição composta

Para um operador opbinário , uma expressão de atribuição composta do formulário

x op= y

é equivalente a

x = x op y

só que só é x avaliado uma vez.

O exemplo a seguir demonstra o uso de atribuição composta com operadores aritméticos:

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

Devido a promoções numéricas, o op resultado da operação pode não ser implicitamente conversível para o tipo T de x. Nesse caso, se op for um operador predefinido e o resultado da operação for explicitamente conversível para o tipo T de , uma expressão de xatribuição composta do formulário x op= y é equivalente a x = (T)(x op y), exceto que x é avaliada apenas uma vez. O exemplo a seguir demonstra esse comportamento:

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

No exemplo anterior, value 44 é o resultado da conversão de value 300 para o byte tipo.

Nota

No contexto de verificação de estouro verificado, o exemplo anterior lança um OverflowExceptionarquivo . Para obter mais informações, consulte a seção Estouro aritmético de inteiros.

Você também usa os += operadores e -= para se inscrever e cancelar a assinatura de um evento, respectivamente. Para obter mais informações, consulte Como se inscrever e cancelar a assinatura de eventos.

Precedência e associatividade do operador

A lista a seguir ordena operadores aritméticos a partir da maior precedência para a mais baixa:

  • Operadores de incremento e decréscimo x++ x-- Postfix
  • Incremento ++x e decréscimo --x de prefixo e unário + e - operadores
  • Multiplicativo *, /e % operadores
  • + Aditivos e - operadores

Os operadores aritméticos binários são associados à esquerda. Ou seja, operadores com o mesmo nível de precedência são avaliados da esquerda para a direita.

Use parênteses, (), para alterar a ordem de avaliação imposta pela precedência do operador e associatividade.

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

Para obter a lista completa de operadores C# ordenados por nível de precedência, consulte a seção Precedência do operador do artigo Operadores C#.

Estouro aritmético e divisão por zero

Quando o resultado de uma operação aritmética está fora do intervalo de possíveis valores finitos do tipo numérico envolvido, o comportamento de um operador aritmético depende do tipo de seus operandos.

Estouro aritmético inteiro

A divisão inteira por zero sempre lança um DivideByZeroException.

Se ocorrer estouro aritmético de inteiros, o contexto de verificação de estouro, que pode ser verificado ou desmarcado, controla o comportamento resultante:

  • Em um contexto verificado, se o estouro acontecer em uma expressão constante, ocorrerá um erro em tempo de compilação. Caso contrário, quando a operação é executada em tempo de execução, um OverflowException é lançado.
  • Em um contexto não verificado, o resultado é truncado descartando quaisquer bits de ordem alta que não se encaixam no tipo de destino.

Junto com as instruções verificadas e não verificadas , você pode usar os checked operadores e unchecked para controlar o contexto de verificação de estouro, no qual uma expressão é avaliada:

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

Por padrão, as operações aritméticas ocorrem em um contexto não verificado .

Estouro aritmético de vírgula flutuante

As operações aritméticas com os float tipos e double nunca lançam uma exceção. O resultado de operações aritméticas com esses tipos pode ser um dos valores especiais que representam infinito e não-um-número:

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

Para os operandos do tipo, o decimal estouro aritmético sempre lança um OverflowException. Divisão por zero sempre lança um DivideByZeroException.

Erros de arredondamento

Devido a limitações gerais da representação de números reais e aritmética de vírgula flutuante, erros de arredondamento podem ocorrer em cálculos com tipos de vírgula flutuante. Ou seja, o resultado produzido de uma expressão pode diferir do resultado matemático esperado. O exemplo a seguir demonstra vários desses casos:

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

Para obter mais informações, consulte comentários nas páginas de referência System.Double, System.Single ou System.Decimal .

Capacidade de sobrecarga do operador

Um tipo definido pelo usuário pode sobrecarregar os operadores aritméticos unários (++, --, +, e -) e binários (*, /, %+, e -). Quando um operador binário está sobrecarregado, o operador de atribuição composto correspondente também é implicitamente sobrecarregado. Um tipo definido pelo usuário não pode sobrecarregar explicitamente um operador de atribuição composta.

Operadores verificados definidos pelo usuário

A partir do C# 11, quando você sobrecarrega um operador aritmético, você pode usar a checked palavra-chave para definir a versão verificada desse operador. O exemplo a seguir mostra como fazer isso:

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

Ao definir um operador verificado, você também deve definir o operador correspondente sem o checked modificador. O operador verificado é chamado em um contexto verificado, o operador sem o checked modificador é chamado em um contexto não verificado. Se você fornecer apenas o operador sem o checked modificador, ele será chamado em um checked e unchecked contexto.

Quando você define ambas as versões de um operador, espera-se que seu comportamento seja diferente apenas quando o resultado de uma operação é muito grande para representar no tipo de resultado da seguinte maneira:

  • Um operador verificado lança um OverflowExceptionarquivo .
  • Um operador sem o checked modificador retorna uma instância que representa um resultado truncado .

Para obter informações sobre a diferença no comportamento dos operadores aritméticos internos, consulte a seção Estouro aritmético e divisão por zero .

Você pode usar o checked modificador somente quando sobrecarregar qualquer um dos seguintes operadores:

Nota

O contexto de verificação de estouro dentro do corpo de um operador verificado não é afetado pela presença do checked modificador. O contexto padrão é definido pelo valor da opção de compilador CheckForOverflowUnderflow. Use as checked instruções and unchecked para especificar explicitamente o contexto de verificação de estouro, como demonstra o exemplo no início desta seção.

Especificação da linguagem C#

Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#:

Consulte também