JavaRush /Java блог /Random /Приведение примитивных типов. Приведение типа int к типу ...
Георгий
22 уровень
Санкт-Петербург

Приведение примитивных типов. Приведение типа int к типу short и byte

Статья из группы Random
Приведение примитивных типов. Приведение типа int к типу short и byte - 1Почему, если привести какие-нибудь значения типа int к типу short или byte, результаты бывают неожиданными? Давайте разбираться!

int i = 450;
byte b = (byte)i;
System.out.println(b);
Результат на экране:

-62
Неожиданно, но этому есть логическое объяснение, более того, это действие можно сделать собственноручно. Для этого, нам нужно перевести 450 из десятичной системы в двоичную:

450/2.    0
225/2.    1
112/2.    0
56/2.     0
28/2.     0
14/2.     0
7/2.      1
3/2.      1
1/2.      1
В правый столбик от числа мы записываем его остаток от деления на 2, а под самим числом пишем результат деления нашего числа на два, если остаток 0. Если остаток 1, то ниже записываем целую часть от деления на два. (Онлайн калькулятор с объяснением вычислений). В итоге, мы получаем, что в двоичной системе счисления 450 = 11100 0010. Любое число типа int занимает 4 байта или 32 бита, где каждый бит - это 0 или 1. В нашем случае заняты только 9 битов, и в принципе наш int i = 450 в двоичной системе выглядит так:

0000_0000_0000_0000_0000_0001_1100_0010
Мы хотим записать нашу переменную в переменную типа byte, но число типа byte занимает 1 байт (следует из названия этого типа) или 8 бит. Поэтому лишние биты слева просто отбрасываются, и в итоге мы получаем:

1100 0010
Диапазон значений типа byte: -128 до 127. Каждое число занимает 8 бит и у каждого числа крайний левый бит - знаковый бит(sign bit). У всех положительных чисел он равен 0, у всех отрицательных он равен 1. Спешить переводить наш результат, полученный выше, в 10-ную систему не нужно, т.к. мы получили дополнительный код искомого числа, а не прямой. Крайний бит слева получился равен 1, следовательно число у нас отрицательное, а у отрицательных чисел прямой и обратный код не совпадает, в отличие от положительных. Если бы знаковый бит был равен 0, то мы могли бы сразу перевести число в десятичную систему счисления и получить: 66. Но знаковый бит отрицательный, поэтому сначала дополнительный код нужно перевести в прямой и добавить к ответу знак минус. Для наглядности и тренировки, сначала попробуем получить дополнительный код какого-нибудь числа, например -15. Для этого в прямом коде его положительного представления (числа 15) нужно поменять все 0 на 1 и наоборот (получить обратный код, также называют инверсный), а затем добавить к результату единицу. В десятичной системе 15 = 0000 1111; Обратный код (меняем все 0 на 1 и наоборот) = 1111 0000; Дополнительный код(прибавляем единицу):

1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 1
1 1 1 1 0 0 0 1
Дополнительный код числа -15: 1111 0001; Отлично.Теперь, по аналогии с примером выше, нам нужно перевести уже наш дополнительный код в прямой, напомню, он равен 1100 0010.
  1. Отнимаем единицу и получаем обратный код. Удобно делать так, записать дополнительный код в ответ и смотреть, к чему нужно прибавить единицу, чтобы получить такой дополнительный код. Начинаем с крайнего правого разряда и смотрим: к чему нужно прибавить 1 чтобы получить 0? К 1, получим 10, 0 уходит в ответ, а единичка на следующий разряд. Далее, что нужно прибавить к 0, чтобы получить один. Единицу, но так как мы с предыдущего разряда имеем единичку, то в ответ пишем 0. Далее, чтобы получить 0, что нужно прибавить к 0? Конечно, 0. Так ещё 4 раза. И остались последние 2 разряда, где к 0 надо что-то прибавить, чтобы получить 1. Конечно, в обоих случаях нужно прибавить 1. Итого:

    
    1 1 0 0 0 0 0 1
    0 0 0 0 0 0 0 1
    1 1 0 0 0 0 1 0
    
  2. Самое сложное позади! Мы получили инверсный(обратный) код и нам осталось получить прямой. Инвертируем все 0 на 1 и наоборот:

    1100 0001 - инверсный код;

    0011 1110 - прямой код нашего числа, точнее его положительного представления;

  3. Переводим в десятичную систему счисления (Онлайн калькулятор с объяснением вычислений):

    0011 1110 = 0∙2^7+0∙2^6+1∙2^5+1∙2^4+1∙2^3+1∙2^2+1∙2^1+0∙2^0 = 0+0+32+16+8+4+2+0 = 62;

    Осталось только добавить к числу минус и наш ответ: -62.

Таким же образом преобразуются числа типа short к типу int:

    int i = 10_000_000;
    short s = (short)i;
    System.out.println(s); // -27008
  1. 10.000.000 в 10-ной системе счисления = 0000 0000 1001 1000 1001 0110 1000 0000 в 2-ной.

    В Java число типа int занимает 4 байта, а short - 2 байта, или 16 бит, поэтому отсекаем слева до 16 цифр:

  2. 1001 0110 1000 0000. Крайний левый бит(старший бит, он же знаковый бит) получился равен 1. Значит перед нами дополнительный код отрицательного числа, поэтому переходим к следующему пункту.
  3. Переводим в обратный код:

    
    1 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 1 0 1 1 0 1 0 0 0 0 0 0 0
    

    Обратный код: 1001 0110 0111 1111;

  4. Инвертируем и получаем прямой код: 0110 1001 1000 0000.

  5. Переводим в двоичную систему счисления и получаем положительное представление нашего числа:

    1∙2^14+1∙2^13+1∙2^11+1∙2^8+1∙2^7 = 16384+8192+2048+256+128 = 27008.
  6. Добавляем минус и получаем ответ: -27008

Приведение примитивных типов. Приведение типа int к типу short и byte - 2Ссылка на онлайн-калькулятор прямого, обратного и дополнительного кода. Также на этом сайте под калькулятором есть немного теории об обратном и дополнительном коде.
Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Daria_Grin Уровень 19
3 мая 2023
Это единственная статья, которую я нашла в инете, где этот вопрос понятно объясняется! Спасибо! Но зачем нужен прямой и обратный коды? Зачем так усложнять? Почему нельзя пользоваться только прямым кодом?
Очень крутая статья! Спасибо!
Ойбек Нурматов Уровень 20
20 июня 2020
отлично мне очень понравилось это статью, полезно
dolcom20 Уровень 5
2 июня 2020
Спасибо за полезную статью! Т.е. если в старшем бите единица, то перед нами дополнительный код отрицательного числа => вычитаем единицу и получаем обратный код, затем инвертируем обратный код, чтобы получить прямой, прямой переводим в десятичную сс и добавляем к нему минус впереди. Гениально, только сложно! 😃
26 апреля 2020
"Почему, если привести какие-нибудь значения типа int к типу short или byte, результаты бывают неожиданными?" Исключительно для тех, кто не знает сути приведения.
Юрий Уровень 31
23 апреля 2020
Хорошая статья!