операция сдвига битов не возвращает ожидаемый результат - PullRequest
6 голосов
/ 27 марта 2012

Почему Java возвращает -2147483648 , когда я сдвигаю бит 1 << 63 </em>?

Ожидаемый результат - 9 223 372 036 854 775 808, протестировано с Wolfram Alpha и моимкалькулятор.

Я проверял:

System.out.print((long)(1 << (63)));

Ответы [ 2 ]

27 голосов
/ 27 марта 2012

Важное замечание по поводу линии

System.out.print((long)(1 << (63)));

Сначала вы берете (1 << 63), а , а затем , которые вы используете на длинные В результате вы фактически смещаетесь влево в целых числах, поэтому длинное приведение не имеет никакого эффекта. Вот почему сдвиг влево на 63 бита дает минимальное целое число, а не минимальное.

Но есть еще один, более важный момент. Длинные Java всегда подписаны, поэтому даже строка

System.out.print(1L << 63);

даст отрицательное число. В дополнение к двум, всякий раз, когда крайний левый бит равен 1, число является отрицательным.

На самом деле вы не можете представить число 2 63 = 9223372036854775808 в примитивном типе Java, поскольку это число больше максимальной длины, а long - самый большой тип примитива. Вы можете представить это число как BigInteger . Вы даже можете сгенерировать его через сдвиг влево на 63 с кодом

BigInteger.ONE.shiftLeft(63)
6 голосов
/ 27 марта 2012

У вас целочисленное переполнение [дважды].

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

Когда вы делаете (long)(1 << (63)), вы только приводите результат 1 << (63) [который равен -2147483648] к long - и это не меняет его значение.

...