Domanda

Perché questo codice 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 si eseguono, output

1
1
107374182400
0

Invece del previsto

1
1
107374182400
107374182400

produzione?

È stato utile?

Soluzione 2

107374182400 è esattamente 25 volte l'intera gamma di un numero intero (2^32), il che significa che se provi a inserirlo in un numero intero lo farà overflow. E poiché si adatterebbe esattamente 25 volte, finisce proprio su 0 (questa è una coincidenza e altre enormi moltiplicazioni possono finire positive o negative). E stai usando un numero intero fino al punto che hai lanciato a lungo

long a1 = 100 * 1024 * 1024 * 1024;

è equivalente a

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

Se metti un singolo lungo nell'espressione, è costretto a usare la matematica non matematica intera che rimuove il problema

Altri suggerimenti

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

In questa operazione tuttavia almeno un operando lo è long. Quindi l'operazione viene eseguita utilizzando precisione a 64 bit e il risultato dell'operatore numerico è di tipo long. L'altro operando non lungo è ampliato per il tipo long di promozione numerica e il valore derivato viene archiviato in variabile a2.

 long a1 = 100 * 1024 * 1024 * 1024;

L'espressione costante di intero semplice, il risultato dell'espressione è stato calcolato come un tipo int. Il valore calcolato tuttavia troppo grande per adattarsi a un numero intero e quindi traboccato, risultando 0 e viene immagazzinato a1 variabile.

EDIT: come viene chiesto nel seguente commento:

Perché non diventa negativo?

Perché mentre sei dentro Calcolo intero Il secondo calcolo è equivalente a 25 * 2^32 dove ^ ha il significato del potere e 2^32 Il valore intero è 0. Tuttavia, per spiegare perché il suo valore è 0: In binario:

 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 è un intero negativo (-2147483648) come è il bit del segno 1 E quindi 2 ^ 32 è solo una moltiplicazione di 2 a 2 ^ 31: uno spostamento a sinistra e il bit del segno diventeranno 0 E quindi il risultato è 0.

Dai un'occhiata al java language specification: 4.2.2: Integer operation per dettagli.

Potrebbe essere che l'espressione a destra di a1 viene prima calcolato come un int e più tardi convertiti in long. Se è uguale 0 come un int rimarrà 0 come un long

Secondo il Documentazione dei letterali lessicali Si dice che,

Il tipo di un letterale è determinato come segue:
- Il tipo di un letterale intero (§3.10.1) che termina con L o L è lungo (§4.2.1).
- Il tipo di qualsiasi altro letterale intero è int (§4.2.1).

Quindi la tua espressione, 100 * 1024 * 1024 * 1024 viene valutato come int Tipo di dati primitivi perché l o L non è menzionato in alcun valore numerico. E il risultato è 107374182400 cioè in binario lo è 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 e int è a 32 bit, quindi a 32 bit sono presi come menzionato in Esempio 4.2.2-1. Operazioni interi che risulta a 0

È anche menzionato nella stessa documentazione che,

Se un operatore intero diverso da un operatore a turni ha almeno un operando di tipo lungo, l'operazione viene eseguita utilizzando precisione a 64 bit e il risultato dell'operatore numerico è di tipo lungo. Se l'altro operando non è lungo, viene prima ampliato (§5.1.5) da digitare a lungo mediante promozione numerica

Significa che qualsiasi valore nell'espressione contiene l o L Quindi tutto il int I valori verranno ampliati a 64 bit.

MODIFICARE In il commento viene anche chiesto

Perché non diventa negativo?

Lo penso anche risponde alla domanda di cui sopra

long a4 = 1L; // nessun problema in questo

long a3 = 1; // Qui la primitiva sul lato sinistro è considerata intera e al momento dell'assegnazione verrà lanciato a lungo, quindi il risultato è come previsto

long a2 = 100L * 1024 * 1024 * 1024; (Qui hai usato 100L, quindi gli altri verranno lanciati a lungo, quindi previsto)

long a1 = 100 * 1024 * 1024 * 1024; (Poiché per impostazione predefinita ogni cifra primitiva è considerata Int in Java, lo considererà come moltiplicazione interi, quindi va fuori portata e si traduce in 0)

Ecco cosa hai fatto: hai assegnato 100 * 1024 * 1024 * 1024a un lungo tipo di dati ma non l'hai detto 100 * 1024 * 1024 * 1024 è un valore lungo

Per impostazione predefinita, il compilatore Java pensa che sia un numero intero. Poiché Integer non può avere così tanto valore, mostrerà un risultato sbagliato. Spero che sia d'aiuto !

la ragione è Overflow Integer
come output di 100 * 1024 * 1024 * 1024; è un intero (int) non long

e in long a2 = 100L * 1024 * 1024 * 1024; Stai specificando che uno dei valore è long (qui 100L) e moltiplicazione con quel valore si traduce in long valore che viene archiviato correttamente in a2

In Java, se hai int * int, calcolerà l'output come int. Dà il risultato solo come un lungo se si fa * lungo. Nel tuo caso, il 100 * 1024 * 1024 * 1024 ha un risultato che overflow int.

Quindi, l'aggiunta di una "L" rende l'operando lungo e il calcolo memorizza i valori a lungo. E, naturalmente, non si verifica alcun overflow e un risultato corretto può essere emesso (cioè A2).

Il numero 3 ha funzionato perché hai specificato un tipo lungo che è 100L. Ecco perché è una lunga moltiplicazione e potrebbe essere immagazzinata. D'altra parte il numero 4 è una moltiplicazione interi con valore massimo 2^32-1 Ecco perché hai ottenuto un overflow e lo zero predefinito valutato è apparso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top