Приведение к байту в Java - PullRequest
       34

Приведение к байту в Java

3 голосов
/ 11 апреля 2011

Я не могу понять следующее:

В Яве

long l = 130L;  
byte b = (byte)l;

Если я напечатаю значение b, почему я получаю -126? Что такое битовое представление long l?

Ответы [ 3 ]

13 голосов
/ 11 апреля 2011

Байт представляет собой последовательность из 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

И теперь все ясно: x + 125 = -1 => x = -126

Вы можете представить значения, организованные по кругу, с 0 сверху (полдень) и положительные значения расположены как на часах от 0 до 5 (но до 127), а также поворотная точка внизу (127 + 1 => -128 [sic!].) Теперь вы можете идти по часовой стрелке, добавив1 приводит к -127, -126, -125, ... -3, -2, -1 (в 11 часов) и, наконец, к 0 снова на вершине.

Для больших чисел (small, int, long) берите большие часы, причем ноль всегда вверху, максимум и минимум всегда внизу.Но даже байт слишком велик, чтобы сделать изображение, поэтому я сделал один полубайт:

bitpatterns of integer, arranged in circle form

Вы можете легко заполнить отверстия вкартина, это тривиально!

Кстати: все это не называется кастинг .Кастинг используется только между объектами.Если у вас есть что-то, что в действительности является подтипом:

 Object o = new String ("casting or not?"); 

, это просто присваивание, поскольку строка (всегда) является объектом.Не используется кастинг.

 String s = (String) o; 

Это кастинг.Для более конкретного типа.Не каждый объект является строкой.Существует небольшая связь с целочисленным продвижением, поскольку каждый байт может быть преобразован без потерь в длинный, но не каждый длинный в байт.Однако даже Byte и Long, типы объектов, не наследуются друг от друга.

Вы просто не получите предупреждение, для

byte s = (byte) 42;
long o = s; // no problem, no warning
byte b = (byte) o; // written like casting 
7 голосов
/ 11 апреля 2011

Байты подписаны в Java - поэтому диапазон значений составляет от -128 до 127 включительно.

Битовая последовательность длиной 130, если ее просто укоротить до 8 бит, является битовой комбинацией для -126.как байт.

В качестве другого примера:

int x = 255;
byte b = (byte) x; // b is now -1
2 голосов
/ 11 апреля 2011

Вы имеете в виду byte b = (byte)l?

Типы Java подписаны, поэтому байты допускают числа от -128 до + 127.

...