Java Language Los operadores aritméticos (+, -, *, /,%)


Ejemplo

El lenguaje Java proporciona 7 operadores que realizan aritmética en valores enteros y de punto flotante.

  • Hay dos operadores +
    • El operador de suma binaria agrega un número a otro. (También hay un operador binario + que realiza la concatenación de cadenas. Esto se describe en un ejemplo separado).
    • El operador Unary Plus no hace nada más que activar la promoción numérica (ver más abajo)
  • Hay dos - operadores:
    • El operador de sustracción binaria resta un número de otro.
    • El operador menos unario es equivalente a restar su operando de cero.
  • El operador de multiplicación binaria (*) multiplica un número por otro.
  • El operador de división binaria (/) divide un número por otro.
  • El operador del resto binario 1 (%) calcula el resto cuando un número se divide por otro.

1. A menudo, esto se conoce incorrectamente como operador de "módulo". "Resto" es el término utilizado por el JLS. "Módulo" y "resto" no son lo mismo.

Operandos y tipos de resultados, y promoción numérica.

Los operadores requieren operandos numéricos y producen resultados numéricos. Los tipos de operandos pueden ser cualquier tipo numérico primitivo (es decir, byte , short , char , int , long , float o double ) o cualquier tipo de contenedor numérico definido en java.lang ; ie ( Byte , Character , Short , Integer , Long , Float o Double .

El tipo de resultado se determina en base a los tipos de operandos u operandos, de la siguiente manera:

  • Si cualquiera de los operandos es double o Double , entonces el tipo de resultado es double .
  • De lo contrario, si alguno de los operandos es float o Float , el tipo de resultado es float .
  • De lo contrario, si alguno de los operandos es long o Long , entonces el tipo de resultado es long .
  • De lo contrario, el tipo de resultado es int . Esto cubre byte , short y char operandos, así como `int.

El tipo de resultado de la operación determina cómo se realiza la operación aritmética y cómo se manejan los operandos

  • Si el tipo de resultado es double , los operandos se promueven a double , y la operación se realiza utilizando aritmética de punto flotante IEE 754 de 64 bits (binario de doble precisión).
  • Si el tipo de resultado es float , los operandos se promueven a float , y la operación se realiza utilizando aritmética de punto flotante IEE 754 de 32 bits (binario de precisión simple).
  • Si el tipo de resultado es long , los operandos se promueven a long , y la operación se realiza utilizando aritmética de enteros binarios de dos bits con signo de 64 bits.
  • Si el tipo de resultado es int , los operandos se promueven a int , y la operación se realiza utilizando aritmética de enteros binarios de dos bits con signo de 32 bits.

La promoción se realiza en dos etapas:

  • Si el tipo de operando es un tipo de envoltura, el valor del operando se desajusta a un valor del tipo primitivo correspondiente.
  • Si es necesario, el tipo primitivo se promueve al tipo requerido:
    • La promoción de enteros a int o long tiene pérdidas.
    • La promoción de float al double tiene pérdidas.
    • La promoción de un número entero a un valor de punto flotante puede llevar a la pérdida de precisión. La conversión se realiza utilizando la semántica "redondeo a más cercano" IEE 768.

El significado de división

El operador / divide el operando izquierdo n (el dividendo ) y el operando derecho d (el divisor ) y produce el resultado q (el cociente ).

La división entera de Java se redondea hacia cero. La Sección 15.17.2 de JLS especifica el comportamiento de la división entera de Java de la siguiente manera:

El cociente producido para los operandos n y d es un valor entero q cuya magnitud es lo más grande posible al tiempo que satisface |d ⋅ q| ≤ |n| . Además, q es positivo cuando |n| ≥ |d| n y d tienen el mismo signo, pero q es negativo cuando |n| ≥ |d| n y d tienen signos opuestos.

Hay un par de casos especiales:

  • Si la n es MIN_VALUE y el divisor es -1, entonces se produce un desbordamiento de enteros y el resultado es MIN_VALUE . No se lanza ninguna excepción en este caso.
  • Si d es 0, entonces se lanza `ArithmeticException.

Java división de punto flotante tiene más casos de borde a considerar. Sin embargo, la idea básica es que el resultado q es el valor más cercano a la satisfacción de d . q = n .

La división de punto flotante nunca dará lugar a una excepción. En cambio, las operaciones que se dividen por cero dan como resultado valores de INF y NaN; vea abajo.

El significado del resto

A diferencia de C y C ++, el operador de resto en Java funciona con operaciones de punto flotante y enteros.

Para casos de enteros, el resultado de a % b se define como el número r tal que (a / b) * b + r es igual a a , donde / , * y + son los operadores enteros de Java apropiados. Esto se aplica en todos los casos, excepto cuando b es cero. En ese caso, el resto da como resultado una ArithmeticException .

De la definición anterior se desprende que a % b puede ser negativo solo si a es negativo, y solo positivo si a es positivo. Además, la magnitud de a % b es siempre menor que la magnitud de b .

La operación de resto de punto flotante es una generalización del caso entero. El resultado de a % b es el resto r se define por la relación matemática r = a - (b ⋅ q) donde:

  • q es un número entero,
  • es negativo solo si a / b es negativo y positivo solo si a / b es positivo, y
  • su magnitud es tan grande como sea posible sin exceder la magnitud del verdadero cociente matemático de a y b .

El resto de punto flotante puede producir valores de INF y NaN en casos de borde, como cuando b es cero; vea abajo. No lanzará una excepción.

Nota IMPORTANTE:

El resultado de una operación de resto de punto flotante calculada por % no es la misma que la producida por la operación de resto definida por IEEE 754. El resto de IEEE 754 se puede calcular utilizando el método de biblioteca Math.IEEEremainder .

Desbordamiento de enteros

Los valores enteros de Java de 32 y 64 bits están firmados y utilizan una representación binaria de dos complementos. Por ejemplo, el rango de números representables como (32 bit) int -2 31 a +2 31 - 1.

Cuando sumas, restas o múltiples enteros de dos bits N (N == 32 o 64), el resultado de la operación puede ser demasiado grande para representarlo como un entero de N bits. En este caso, la operación conduce a un desbordamiento de enteros , y el resultado se puede calcular de la siguiente manera:

  • La operación matemática se realiza para dar una representación intermedia de complemento de dos de todo el número. Esta representación será mayor que N bits.
  • Los 32 o 64 bits inferiores de la representación intermedia se utilizan como resultado.

Cabe señalar que el desbordamiento de enteros no da lugar a excepciones en ningún caso.

Valores de punto flotante INF y NAN

Java utiliza representaciones de punto flotante IEE 754 para float y double . Estas representaciones tienen algunos valores especiales para representar valores que están fuera del dominio de los números reales:

  • Los valores "infinitos" o INF denotan números que son demasiado grandes. El valor +INF denota números que son demasiado grandes y positivos. El valor -INF denota números que son demasiado grandes y negativos.
  • El "indefinido" / "no un número" o NaN denota valores resultantes de operaciones sin sentido.

Los valores INF son producidos por operaciones flotantes que causan desbordamiento, o por división por cero.

Los valores de NaN se producen dividiendo cero por cero, o calculando cero resto cero.

Sorprendentemente, es posible realizar aritmética utilizando operandos INF y NaN sin desencadenar excepciones. Por ejemplo:

  • Sumando + INF y un valor finito da + INF.
  • Sumando + INF y + INF da + INF.
  • Añadiendo + INF y -INF da NaN.
  • La división por INF da +0.0 o -0.0.
  • Todas las operaciones con uno o más operandos de NaN dan NaN.

Para obtener más detalles, consulte las subsecciones relevantes de JLS 15 . Tenga en cuenta que esto es en gran parte "académico". Para cálculos típicos, un INF o NaN significa que algo ha salido mal; por ejemplo, tiene datos de entrada incompletos o incorrectos, o el cálculo se ha programado incorrectamente.