Приведение длинных байтов в 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.

Другие вопросы по тегам