Приведение длинных байтов в Java
Я не могу понять следующее:
В яве,
long l = 130L;
byte b = (byte)l;
Если я печатаю значение b, почему я получаю -126? Что такое битовое представление long l?
5 ответов
Байты подписаны в Java - поэтому диапазон значений составляет от -128 до 127 включительно.
Битовая комбинация длиной 130, если ее просто укоротить до 8 бит, является битовой комбинацией для -126 в виде байта.
В качестве другого примера:
int x = 255;
byte b = (byte) x; // b is now -1
Байт представляет собой последовательность из 8 битов, что составляет 2^8 случаев = 256. Половина из них представляет отрицательные числа, которые составляют от -128 до -1. Тогда есть 0, и примерно половина, от 1 до 127 представляют положительные числа.
130 как Int выглядит как 128 + 2, что:
0000:0000 1000:0000 (128)
0000:0000 0000:0010 (2)
0000:0000 1000:0010 (130)
Тем не менее, байт имеет всего 8 цифр, и присвоение принимает только те биты, которые есть, но только последние:
1000:0010
Первый бит указывает, что это отрицательное число. Теперь, сколько вам нужно добавить, чтобы добраться до нуля? Давайте сделаем это пошагово:
1000:0010 x +
0000:0001 1 =
----------------
1000:0011 (x+1)
1000:0011 (x+1) +
0000:0001 1 =
----------------
1000:0100 (x+2)
Давайте сделаем большие шаги. Просто добавьте 1, где у нас есть нули, но сначала мы вернемся к x:
1000:0010 x +
0111:1101 y =
--------------
1111:1111
Теперь есть поворотный момент: мы добавляем еще 1 и получаем ноль (плюс переполнение)
1111:1111 (x + y) +
0000:0001 1
---------
0000:0000 0
Если (x+y) + 1 = 0, x+y = -1. Интересно, что минус 1 - это не то же самое, что 1 (0000:0001) с набором "отрицательных флагов" ("1000:0001"), но выглядит совершенно иначе. Тем не менее, первая позиция всегда говорит вам знак: 1 всегда обозначает отрицательный.
Но что мы добавили раньше?
0111:1101 y = ?
У него нет 1 на первой позиции, поэтому это положительное значение. Мы знаем, как это разобрать?
..f:8421 Position of value (1, 2, 4, 8, 16=f, 32, 64 in opposite direction)
0111:1101 y = ?
..f 84 1 = 1+4+8+16+32+64= 125
И теперь понятно: х +125 = -1 => х = -126
Вы можете представить себе значения, организованные по кругу, с 0 сверху (высокий полдень) и положительными значениями, расположенными как на часах от 0 до 5 (но до 127), и поворотной точкой внизу (127 + 1). => -128 [sic!].) Теперь вы можете продолжать по часовой стрелке, добавив 1 отведения к -127, -126, -125, ... -3, -2, -1 (в 11 часов) и, наконец, 0 снова наверху.
Для больших чисел (small, int, long) берут большие часы, причем ноль всегда вверху, максимум и минимум всегда внизу. Но даже байт слишком велик, чтобы сделать картинку, поэтому я сделал один клочок, полубайта:
Вы можете легко заполнить отверстия на картинке, это тривиально!
Кстати: все это не называется кастингом. Кастинг используется только между объектами. Если у вас есть что-то, что в действительности является подтипом:
Object o = new String ("casting or not?");
это просто присваивание, так как строка (всегда) является объектом. Нет кастинга.
String s = (String) o;
Это кастинг. Для более конкретного типа. Не каждый объект является строкой. Существует небольшая связь с целочисленным продвижением, так как каждый байт может быть преобразован без потерь в длинный, но не каждый длинный в байт. Однако, даже Byte и Long, Object-типы, не наследуются друг от друга.
Вы просто не получите предупреждение, для
byte s = (byte) 42;
long o = s; // no problem, no warning
byte b = (byte) o; // written like casting
Ты имеешь в виду byte b = (byte)l
?
Типы Java подписаны, поэтому байты допускают числа от -128 до +127.
Для понимания новичками: 1 байт = 8 битов битов Таким образом, диапазон от -128 до 127
Всякий раз, когда значение увеличивается больше, чем максимально возможное значение +ve, поток переходит к наименьшему возможному значению -ve.
Таким образом, после того, как значение достигает 127 , поток продолжается от -128 до -127 и до -126, чтобы покрыть общее пространство 130, и, таким образом, o/p равно -126.
Беззнаковый байт содержит значения от 0 до 255, поэтому в него может поместиться число 130, но когда это знаковый байт, оно может достигать только 127, поэтому 130 не будет храниться должным образом.
Поскольку число хранится в формате дополнения до двух, вы можете вычесть 256, если число больше 127. 130 больше 127, поэтому 130 – 256 = -126.
Также имейте в виду, что все остальные биты после первых 8 будут потеряны. Если у вас длинный valLong = 257, то есть 9 бит, поэтому при преобразовании в байт он теряет некоторую информацию и становится значением 1 (257, поскольку длинный равен 00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000001 но байт может содержать только последнюю часть: 00000001.