Comparteix via


Operadores aritméticos (referencia de C#)

Los operadores siguientes realizan operaciones aritméticas con operandos de tipos numéricos:

Todos los tipos numéricos enteros y de punto flotante admiten estos operadores.

Los inttipos , uint, longy ulong definen todos estos operadores. Los otros tipos enteros (sbyte, byte, short, ushorty char) definen solo los ++ operadores y -- . Para los otros operadores, si usa los tipos sbyteenteros , , shortbyte, ushorto char como operandos, los valores se convierten en el int tipo y el tipo de resultado es int. Si los operandos son tipos enteros o de punto flotante diferentes, sus valores se convierten al tipo contenedor más cercano, si existe dicho tipo. Para obtener más información, vea la sección Promociones numéricas de Especificación del lenguaje C#. Los operadores ++ y -- se definen para todos los tipos numéricos enteros y de punto flotante y el tipo char. El tipo de resultado de una expresión de asignación compuesta es el tipo del operando izquierdo.

La documentación de referencia del lenguaje C# cubre la versión más reciente publicada del lenguaje C#. También contiene documentación inicial sobre las características de las versiones preliminares públicas de la próxima versión del lenguaje.

La documentación identifica cualquier característica introducida por primera vez en las últimas tres versiones del idioma o en las versiones preliminares públicas actuales.

Sugerencia

Para buscar cuándo se introdujo por primera vez una característica en C#, consulte el artículo sobre el historial de versiones del lenguaje C#.

Operador de incremento ++

El operador de incremento unario ++ incrementa su operando en 1. El operando debe ser una variable, un acceso de propiedad o un acceso de indexador.

El operador de incremento se admite en dos formas: el operador de incremento posfijo (x++) y el operador de incremento prefijo (++x).

Operador de incremento de postfijo

El resultado de x++ es el valor de xantes de la operación, tal y como se muestra en el ejemplo siguiente:

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

Operador de incremento prefijo

El resultado de ++x es el valor de xdespués de la operación, tal y como se muestra en el ejemplo siguiente:

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

Operador de decremento --

El operador de decremento unario -- disminuye su operando en 1. El operando debe ser una variable, un acceso de propiedad o un acceso de indexador.

El operador decremento está disponible en dos formas: el operador postfix decrement, x--y el operador decremento de prefijo, --x.

Operador de decremento de postfijo

El resultado de x-- es el valor de xantes de la operación, tal y como se muestra en el ejemplo siguiente:

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

Operador de decremento de prefijo

El resultado de --x es el valor de xdespués de la operación, tal y como se muestra en el ejemplo siguiente:

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

Operadores unarios más y menos

El operador + unario devuelve el valor de su operando. El operador unario - calcula la negación numérica del 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

El operador unario no es compatible con el tipo -.

Operador de multiplicación *

El operador de multiplicación * calcula el producto de sus 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

El operador unario * es el operador de direccionamiento indirecto del puntero.

Operador de división /

El operador de división / divide el operando izquierdo entre el derecho.

División de enteros

Para los operandos de tipos enteros, el resultado del / operador es de un tipo entero y es igual al cociente de los dos operandos redondeados hacia cero:

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 obtener el cociente de los dos operandos como un número de punto flotante, use el floattipo , doubleo decimal :

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

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

División de punto flotante

Para los floattipos , doubley decimal , el / operador devuelve el cociente de los dos 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

Si un operando es decimal, el otro operando no puede ser float o double, porque ni ni floatdouble tiene una conversión implícita a decimal. Debe convertir explícitamente el operando float o double al tipo decimal. Para obtener más información sobre las conversiones entre tipos numéricos, consulte Conversiones numéricas integradas.

Operador de resto %

El operador de resto % calcula el resto después de dividir el operando izquierdo entre el derecho.

Resto entero

Para operandos de tipos enteros, el resultado de a % b es el valor generado por $a - \frac{a}{b} \times b$. El signo del resto distinto de cero coincide con el signo del operando izquierdo, como se muestra en el ejemplo siguiente:

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 el método Math.DivRem para calcular los resultados de la división de enteros y del resto.

Resto de punto flotante

En el caso de los operandos float y double, el resultado de x % y para x e y finitos es el valor z, de modo que

  • El signo de z, si no es cero, coincide con el signo de x.
  • El valor absoluto de z procede del cálculo $|x| - n \times |y|$, donde n es el entero más grande menor o igual que $\frac{|x|}{|y|}$. Aquí, $|x|$ y $|y|$ representan los valores absolutos de x y y, respectivamente.

Nota:

Este método de cálculo del resto es similar al método utilizado para operandos enteros, pero difiere de la especificación IEEE 754. Si necesita la operación de resto conforme con la especificación IEEE 754, use el método Math.IEEERemainder.

Para información sobre el comportamiento del operador % con operandos no finitos, vea la sección Operador de resto de la Especificación del lenguaje C#.

En decimal el caso de los operandos, el operador % de resto funciona igual que el operador de resto del System.Decimal tipo.

En el ejemplo siguiente se muestra cómo se comporta el operador de resto con operandos de punto flotante:

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 suma +

El operador de suma + calcula la suma de sus operandos:

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

También puede usar el operador + para la concatenación de cadenas y la combinación de delegados. Para obtener más información, consulte Operadores + y +=.

Operador de resta -

El operador - de resta resta el operando derecho del operando izquierdo:

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

También puede usar el - operador para quitar un delegado. Para obtener más información, consulte los - operadores y -=.

Asignación compuesta

Para un operador binario op, una expresión de asignación compuesta con el formato

x op= y

Es equivalente a

x = x op y

Excepto que x solo se evalúe una vez.

En el ejemplo siguiente se muestra el uso de la asignación compuesta con 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

Debido a las promociones numéricas, es posible que el resultado de la op operación no se pueda convertir implícitamente en el tipo T de x. En tal caso, si op es un operador predefinido y el resultado de la operación es convertible de forma explícita en el tipo T de x, una expresión de asignación compuesta con el formato x op= y es equivalente a x = (T)(x op y), excepto que x solo se evalúa una vez. En el ejemplo siguiente se muestra ese comportamiento:

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

En el ejemplo anterior, el valor 44 es el resultado de convertir el valor 300 al tipo byte.

Nota:

En un contexto de comprobación de desbordamiento de tipo checked, el ejemplo anterior produce una excepción OverflowException. Para obtener más información, consulte la sección Desbordamiento aritmético de enteros.

Los operadores += y -= también se usan para suscribirse y cancelar la suscripción a un evento, respectivamente. Para obtener más información, vea Procedimiento para suscribir y cancelar la suscripción a eventos.

Prioridad y asociatividad de los operadores

En la lista siguiente se ordena a los operadores aritméticos de mayor prioridad a la prioridad más baja:

  • Operadores de incremento x++ y decremento x-- posfijos
  • Operadores de incremento ++x y decremento --x de prefijo, y operadores unarios + y -
  • Operadores de multiplicación *, / y %.
  • Operadores de suma adición + y -.

Los operadores aritméticos binarios son asociativos a la izquierda. Es decir, el compilador evalúa los operadores con el mismo nivel de precedencia de izquierda a derecha.

Use los paréntesis, (), para cambiar el orden de evaluación impuesto por la prioridad y la asociatividad de operadores.

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 obtener la lista completa de los operadores de C# ordenados por nivel de prioridad, vea la sección Prioridad de operadores del artículo Operadores de C#.

Desbordamiento aritmético y división por cero

Si el resultado de una operación aritmética está fuera del intervalo de valores finitos posibles del tipo numérico implicado, el comportamiento de un operador aritmético depende del tipo de sus operandos.

Desbordamiento aritmético de enteros

La división de enteros por cero siempre produce una DivideByZeroException.

En el caso de desbordamiento aritmético de enteros, el comportamiento resultante lo controla el contexto de comprobación de desbordamiento, que puede ser comprobado o no comprobado:

  • En un contexto comprobado, si el desbordamiento se produce en una expresión constante, se produce un error de compilación. De lo contrario, si la operación se realiza en tiempo de ejecución, se inicia una excepción OverflowException.
  • En un contexto no comprobado, el resultado se trunca mediante el descarte de los bits de orden superior que no caben en el tipo de destino.

Nota:

La división de enteros tiene un caso especial en el que se puede producir un ArithmeticException elemento incluso en un contexto no comprobado. Cuando el operando izquierdo es el valor mínimo de un tipo entero con signo (int.MinValue o long.MinValue) y el operando derecho es -1, el resultado no se puede representar en el tipo de destino. El entorno de ejecución de .NET produce una ArithmeticException excepción en este caso, como se muestra en el ejemplo siguiente:

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

Junto con las instrucciones comprobadas y no comprobadas, puede usar los operadores checked y unchecked para controlar el contexto de comprobación de desbordamiento, en el que se evalúa una expresión:

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

De forma predeterminada, las operaciones aritméticas se producen en un contexto no comprobado.

Desbordamiento aritmético de punto flotante

Las operaciones aritméticas mediante el uso de los float tipos y double nunca producen una excepción. El resultado de las operaciones aritméticas que usan esos tipos puede ser uno de los valores especiales que representan infinitos y no números:

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 los operandos del tipo decimal, el desbordamiento aritmético siempre inicia una excepción OverflowException. La división decimal por cero siempre produce una excepción DivideByZeroException.

Errores de redondeo

Debido a las limitaciones generales en la representación de punto flotante de números reales y aritmética de punto flotante, los errores de redondeo pueden producirse en cálculos que usan tipos de punto flotante. El resultado de una expresión puede diferir del resultado matemático esperado. En el ejemplo siguiente se muestran varios de estos 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 obtener más información, vea los comentarios en las páginas de referencia System.Double, System.Single o System.Decimal .

Posibilidad de sobrecarga del operador

Puede sobrecargar los operadores unarios (++, --, +y -) y binarios (*, /, %, +y -) para un tipo definido por el usuario. Al sobrecargar un operador binario, también sobrecarga implícitamente el operador de asignación compuesta correspondiente. A partir de C# 14, un tipo definido por el usuario puede sobrecargar explícitamente los operadores de asignación compuesta (op=) para proporcionar una implementación más eficaz. Normalmente, un tipo sobrecarga estos operadores porque el valor se puede actualizar en su lugar, en lugar de asignar una nueva instancia para almacenar el resultado de la operación. Si un tipo no proporciona una sobrecarga explícita, el compilador genera la sobrecarga implícita.

Operadores comprobados definidos por el usuario

Al sobrecargar un operador aritmético, puede usar la checked palabra clave para definir la versión comprobada de ese operador. En el siguiente ejemplo se muestra cómo hacerlo:

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

Al definir un operador comprobado, también debe definir el operador correspondiente sin el modificador checked. Un contexto comprobado llama al operador comprobado y un contexto desmarcado llama al operador sin el checked modificador .

Cuando se definen ambas versiones de un operador, su comportamiento solo difiere cuando el resultado de una operación es demasiado grande para representar en el tipo de resultado como se indica a continuación:

  • Un operador comprobado produce un OverflowException.
  • Un operador sin el modificador checked devuelve una instancia que representa un resultado truncado.

Para obtener información sobre la diferencia en el comportamiento de los operadores aritméticos integrados, consulte la sección Desbordamiento aritmético y división por cero.

Puede usar el modificador checked solo cuando sobrecarga cualquiera de los operadores siguientes:

Nota:

El checked modificador no afecta al contexto de comprobación de desbordamiento dentro de su cuerpo. El contexto predeterminado se define mediante el valor de la opción del compilador CheckForOverflowUnderflow . Use las instrucciones checked y unchecked para especificar explícitamente el contexto de comprobación de desbordamiento, como se muestra en el ejemplo al principio de esta sección.

Especificación del lenguaje C#

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:

Consulte también