Perché Java tornare -2147483648 quando I bit spostare ?po 'non rendimento atteso risultato
Il risultato atteso è 223 372 036 9 854 775 808, testati con Wolfram Alpha e la mia calcolatrice ..
ho provato:
System.out.print ((lungo) (1 < < (63)));
Perché Java tornare -2147483648 quando I bit spostare ?po 'non rendimento atteso risultato
Il risultato atteso è 223 372 036 9 854 775 808, testati con Wolfram Alpha e la mia calcolatrice ..
ho provato:
System.out.print ((lungo) (1 < < (63)));
C'è una cosa importante da notare circa la linea
System.out.print((long)(1 << (63)));
Per prima cosa prendete (1 << 63)
, e poi lanci a lunga. Di conseguenza, in realtà stai spostando a sinistra in numeri interi, quindi il cast lungo non ha alcun effetto. Ecco perché lo spostamento di 63 bit a sinistra fornisce il numero intero minimo anziché il valore minimo.
Ma c'è un altro punto, più importante. I long Java sono sempre firmati, quindi anche la riga
System.out.print(1L << 63);
darebbe un numero negativo. Sotto il complemento a due, ogni volta che il bit più a sinistra è un 1 il numero è negativo.
In realtà non può rappresentare il numero 2 = 9223372036854775808 in un tipo primitivo Java, perché questo numero è più grande della massima lunghezza, ed è la più grande long
tipo primitivo. È possibile rappresentare questo numero come BigInteger, tuttavia. È anche possibile generare tramite un sinistra-shift del 63 con il codice
BigInteger.ONE.shiftLeft(63)
si stanno avendo un integer overflow [due volte].
1 << 32 == 1
1 << 31 == -2147483648 [ becuase this is the binary representation in 2's complement for -2147483648]
1 << 63 == 1 << (32 + 31) == (1 << 32) << 31 == 1 << 31 == -2147483648
Quando si esegue (long)(1 << (63))
si è solo getto del risultato di 1 << (63)
[che è -2147483648
] per un long
- e non cambia il suo valore.
Grazie per aver segnalato e descritto lo straripamento! Ho cercato una spiegazione a questo codice trovato nell'implementazione BitSet di OpenJDK: [long firstWordMask = WORD_MASK << fromIndex; long lastWordMask = WORD_MASK >>> -toIndex; ] anche se in questo caso WORD_MASK è lungo. – ruizpauker
Oh grazie, è davvero chiaro ora –
+1 per un'ottima risposta, che include anche una soluzione pratica. post scriptum Spero non ti dispiaccia che mi sono preso la libertà di modificare 2^63 in qualcosa di più leggibile. – amit
@amit No, non mi dispiace affatto. Grazie! –