Operadores aritméticos (referência C#)
Os operadores a seguir executam operações aritméticas com operandos de tipos numéricos:
- Operadores unários
++
(incremento),--
(decréscimo),+
(mais) e-
(menos) - Operadores binários (multiplicação),
/
(divisão),%
(restante),+
(adição) e-
(subtração)*
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 int
tipos , 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 short
operação. byte
sbyte
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
, double
ou 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
, double
e 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
, double
porque 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
z
zero, é o mesmo que o sinal dex
. - O valor absoluto de
z
é o valor produzido por|x| - n * |y|
onden
é o maior inteiro possível que é menor ou igual a|x| / |y|
e|x|
e|y|
são os valores absolutos dex
ey
, 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 op
biná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 x
atribuiçã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:
- Unário
++
,--
, e-
operadores - Binário
*
,/
,+
e-
operadores - Operadores de conversão explícitos
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#:
- Operadores de incremento e decréscimo Postfix
- Operadores de incremento e decréscimo de prefixo
- Unary plus operador
- Unary menos operador
- Operador de multiplicação
- Operador de divisão
- Operador restante
- Operador de adição
- Operador de subtração
- Atribuição composta
- Os operadores controlados e não controlados
- Promoções numéricas