Pergunta

Por que esse código Java

long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);

Quando executado, saída

1
1
107374182400
0

em vez do esperado

1
1
107374182400
107374182400

resultado?

Foi útil?

Solução 2

107374182400 é exatamente 25 vezes a faixa completa de um número inteiro (2^32), o que significa que se você tentar encaixá -lo em um número inteiro, será transbordar. E porque se encaixaria exatamente 25 vezes, acaba precisamente em 0 (essa é uma coincidência e outras enormes multiplicações podem acabar positivas ou negativas). E você está usando um número inteiro até o ponto que você lançará para muito tempo

long a1 = 100 * 1024 * 1024 * 1024;

é equivalente a

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

Se você colocar um único tempo na expressão, é forçado a usar matemática longa e não inteira matemática que remove o problema

Outras dicas

 long a2 = 100L * 1024 * 1024 * 1024;

Nesta operação, no entanto, pelo menos um operando é long. Portanto, a operação é realizada usando precisão de 64 bits e o resultado do operador numérico é do tipo long. O outro operando não longo é ampliado para digitar long por Promoção numérica e o valor resultante é armazenado para variável a2.

 long a1 = 100 * 1024 * 1024 * 1024;

A expressão constante de número inteiro simples, o resultado da expressão foi calculado como um tipo int. O valor calculado, porém grande demais, para caber em um número inteiro e, portanto, transbordado, resultando em 0 e é armazenado para a1 variável.

EDIT: Como é perguntado no seguinte comentário:

Por que não é negativo?

Porque enquanto entra Computação inteira o segundo cálculo é equivalente a 25 * 2^32 Onde ^ tem o significado do poder e 2^32 O valor inteiro é 0. No entanto, para explicar por que seu valor é 0: Em binário:

 100 * 1024 * 1024 * 1024 == 25 * 2^32;

 Integer.MAX_VALUE =  2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
 Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000 

2 ^ 31 é um número inteiro negativo (-2147483648) como a parte do sinal é 1 E, portanto 2 ^ 32 é apenas uma multiplicação de 2 para 2 ^ 31: um turno esquerdo e a parte do sinal se tornará 0 e, portanto, o resultado é 0.

Confira o java language specification: 4.2.2: Integer operation para detalhes.

Pode ser que a expressão à direita de a1 é calculado primeiro como um int e mais tarde convertido para long. Se for igual 0 Como um int vai ficar 0 como um long

Conforme Documentação de literais lexicais é mencionado que,

O tipo de um literal é determinado da seguinte maneira:
- O tipo de um número inteiro literal (§3.10.1) que termina com L ou L é longo (§4.2.1).
- O tipo de qualquer outro literal inteiro é int (§4.2.1).

Assim sua expressão, 100 * 1024 * 1024 * 1024 é avaliado como int Tipo de dados primitivo porque l ou L não é mencionado em nenhum valor numérico. E o resultado é 107374182400 ou seja, em binário é 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 e int é de 32 bits tão baixos de 32 bits são tomados como mencionado em Exemplo 4.2.2-1. Operações inteiras que resulta em 0

Também é mencionado na mesma documentação que,

Se um operador inteiro que não seja um operador de turno tiver pelo menos um operando do tipo longo, a operação é realizada usando precisão de 64 bits e o resultado do operador numérico for do tipo longo. Se o outro operando não for longo, ele será ampliado (§5.1.5) para digitar longa por promoção numérica

Isso significa que qualquer valor na expressão contém l ou L então tudo int Os valores serão expandidos para 64 bits.

EDITAR Dentro o comentário também é perguntado

Por que não é negativo?

Eu acho que também responde à pergunta acima

long a4 = 1L; // nenhum problema nisso

long a3 = 1; // aqui o Primitivo do lado esquerdo é considerado como inteiro e, no momento da tarefa, será lançado por muito tempo, o resultado é o esperado

long a2 = 100L * 1024 * 1024 * 1024; (Aqui você usou 100L para que outros sejam do tipo escalado para a saída longa, para que a saída esperada)

long a1 = 100 * 1024 * 1024 * 1024; (Como por padrão, qualquer dígito primitivo é considerado int em Java, ele considerará isso como multiplicação inteira, para que sai do alcance e resulte em 0)

Aqui está o que você fez: você designou 100 * 1024 * 1024 * 1024para um tipo de dados longo, mas você não disse isso 100 * 1024 * 1024 * 1024 é um valor longo

Por padrão, o compilador Java acha que é um número inteiro. Como o número inteiro não pode conter tanto valor, mostrará o resultado errado. Espero que ajude !

a razão é transbordamento inteiro
como saída de 100 * 1024 * 1024 * 1024; é um número inteiro (int) não long

e em long a2 = 100L * 1024 * 1024 * 1024; você está especificando que um dos valores é long (aqui 100L) e multiplicação com esse valor resulta em long valor que é armazenado corretamente em a2

Em Java, se você tiver int * int, ele calculará a saída como um int. Ele apenas dá o resultado por muito tempo se você o fizer * longo. No seu caso, o 100 * 1024 * 1024 * 1024 tem um resultado que transborda int.

Portanto, adicionar um "L" faz com que o operando seja um longo e a computação armazena os valores em muito tempo. E, é claro, não ocorre excesso e um resultado correto pode ser emitido (ou seja, A2).

O número 3 funcionou porque você especificou um tipo longo que é 100L. É por isso que é uma longa multiplicação e pode ser armazenada. Por outro lado, o número 4 é uma multiplicação inteira com o valor máximo 2^32-1, é por isso que você tem um estouro e o valor zero de valor apareceu.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top