una sume suma reste resta que programa operaciones numeros multiplique multiplicacion modo metodos hacer grafico formulario divida con como codigo calculadora basicas java int long-integer multiplication operation

suma - programa en java que sume reste multiplique y divida dos numeros



¿Por qué estas dos operaciones de multiplicación dan resultados diferentes? (2)

¿Por qué tengo que agregar una letra "L" para obtener el valor largo correcto? ¿Y cuál es el otro valor?

long oneYearWithL = 1000*60*60*24*365L; long oneYearWithoutL = 1000*60*60*24*365; System.out.println(oneYearWithL);//gives correct calculation result : 31536000000 System.out.println(oneYearWithoutL)//gives incorrect calculation result: 1471228928


Sin L su cálculo se lleva a cabo como un valor de 32 bits. Si expresa los valores como hexadecimales, el valor más pequeño es solo los 4 bytes más bajos del valor más grande.

Java adopta por defecto el tipo entero de 32 bits. La L , por Long, es de 64 bits. Al poner L después de 365 , le está diciendo al compilador que trate 365 como un valor long . Cuando se multiplican los valores de 32 y 64 bits, el compilador sube el valor de 32 bits a 64 bits, de modo que los resultados intermedios en la evaluación de su expresión retienen el rango completo de 64 bits.

Consulte Tipos y valores primitivos en la Especificación del lenguaje Java .

El comportamiento de la multiplicación se define explícitamente en https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.1 , de la siguiente manera:

15.17.1 Operador de multiplicación *

El operador binario * realiza la multiplicación, produciendo el producto de sus operandos. La multiplicación es una operación conmutativa si las expresiones del operando no tienen efectos secundarios. Mientras que la multiplicación entera es asociativa cuando los operandos son todos del mismo tipo, la multiplicación de coma flotante no es asociativa. Si una multiplicación de enteros se desborda, entonces el resultado son los bits de bajo orden del producto matemático como se representa en algún formato de complemento de dos suficientemente grande. Como resultado, si ocurre un desbordamiento, entonces el signo del resultado puede no ser el mismo que el signo del producto matemático de los dos valores de operando.

El resultado de una multiplicación de coma flotante se rige por las reglas de la aritmética IEEE 754:

  • Si cualquiera de los operandos es NaN , el resultado es NaN .
  • Si el resultado no es NaN , el signo del resultado es positivo si ambos operandos tienen el mismo signo y negativo si los operandos tienen signos diferentes.
  • La multiplicación de infinito por cero da como resultado NaN.
  • La multiplicación de un infinito por un valor finito da como resultado un infinito con signo. El signo está determinado por la regla establecida anteriormente.
  • En los casos restantes, en los que no interviene ni un infinito ni un NaN, se calcula el producto matemático exacto. A continuación, se elige un conjunto de valores de coma flotante:
    • Si la expresión de multiplicación es FP-estricta (§15.4):
      • Si el tipo de expresión de multiplicación es float , se debe elegir el valor de flotación establecido.
      • Si el tipo de expresión de multiplicación es el double , se debe elegir el doble valor establecido.
    • Si la expresión de multiplicación no es FP-estricta:
      • Si el tipo de la expresión de multiplicación es float , entonces se puede elegir ya sea el conjunto de valores flotantes o el conjunto de valores flotantes extendidos-exponentes, según el capricho de la implementación.
      • Si el tipo de la expresión de multiplicación es el double , se puede elegir ya sea el conjunto de valores dobles o el conjunto de valores de doble extensión extendida, por el capricho de la implementación.

A continuación, se debe elegir un valor del conjunto de valores elegido para representar el producto.

Si la magnitud del producto es demasiado grande para representarlo, decimos que la operación se desborda; el resultado es entonces un infinito de signo apropiado.

De lo contrario, el producto se redondea al valor más cercano en el valor elegido mediante el modo IEEE 754 de redondeo a más cercano. El lenguaje de programación Java requiere soporte de subdesbordamiento gradual según lo definido por IEEE 754 (§4.2.4).

A pesar de que puede ocurrir un desbordamiento, subdesbordamiento o pérdida de información, la evaluación de un operador de multiplicación * nunca arroja una excepción de tiempo de ejecución.


long oneYearWithL = 1000*60*60*24*365L; long oneYearWithoutL = 1000*60*60*24*365;

Su primer valor es en realidad un largo (ya que 365L es un número long , y 1000*60*60*24 es un integer , por lo que el resultado de multiplying un valor long con un valor integer es un valor long .

Pero el segundo valor es un número entero (ya que está mulitiplicando un valor integer solo con un valor integer . Por lo tanto, el resultado será un entero de 32-bit . Ahora el resultado obtenido para esa multiplication está fuera del rango real del número entero. Por lo tanto, antes de obtener asignado a la variable, se trunca para encajar en un rango entero válido.

Eche un vistazo a la siguiente declaración impresa:

System.out.println(1000*60*60*24*365L); System.out.println(1000*60*60*24*365); System.out.println(Integer.MAX_VALUE);

Cuando ejecuta el código anterior:

Salida: -

31536000000 1471228928 2147483647

Entonces, puedes ver la diferencia ...

011101010111101100010010110000000000 -- Binary equivalent of 1000*60*60*24*365L 01111111111111111111111111111111 -- Binary equivalent of Integer.MAX_VALUE

Entonces, si no agrega esa L al final de su número, los 4 bits más significativos se eliminan de la primera cadena binaria.

Entonces, la cuerda se convierte en ...

(0111)01010111101100010010110000000000 -- Remove the most significant bits.. 01010111101100010010110000000000 -- Binary equivalent of 1471228928

(que obtienes como salida)

ACTUALIZACIÓN: - De la explicación anterior, también puedes entender que, incluso en la primera asignación, si el resultado de tu multiplication de integers antes de multiplicarlo con 365L queda fuera de rango, entonces nuevamente se truncará para encajar en un rango entero. o se convierte a 2''s complement representation si es necesario, y luego solo se multiplicará con el long value - 365L .

Por ejemplo: -

long thirtyYearWithL = 1000*60*60*24*30*365L;

En el ejemplo anterior, considere la primera parte: 1000*60*60*24*30 . El resultado de esta multiplicación es: - 2592000000 . Ahora veamos cómo se representa en el binary equivalent :

2592000000 = 10011010011111101100100000000000 -- MSB is `1`, a negative value 01100101100000010011100000000001 -- 2''s complement representation

La representación decimal de la representación del 2''s complement es 1702967297 . Entonces, 2592000000 se convierte a -1702967297 , antes de multiplicarse a 365L . Ahora bien, este valor se ajusta en el integer range que es: - [-2147483648 to 2147483647] , por lo que no se truncará más.

Entonces, el resultado real será:

long thirtyYearWithL = 1000*60*60*24*30*365L; = 2592000000 * 365L; = -1702967297 * 365L = -621583063040

Entonces, todas estas cosas solo consideran el type real de resultado final al aplicar la operación aritmética. Y esta comprobación se realiza en cada resultado temporal de las operaciones que se mueven de left to right (considerando operadores con asociatividad de left-to-right ). Si se encuentra que algún resultado temporal está fuera de rango, entonces se convierte de acuerdo para que se ajuste al rango requerido, antes de avanzar con la siguiente operación.

ACTUALIZACIÓN 2: -

Entonces, en lugar de:

long thirtyYearWithL = 1000*60*60*24*30*365L;

si mueve su 365L al inicio, obtendrá el resultado correcto: -

long thirtyYearWithL = 365L*1000*60*60*24*30; // will give you correct result

Porque, ahora su resultado temporary será de tipo long , y es capaz de mantener ese valor.