Как Java конвертирует int в байты?

int i =132; byte b =(byte)i; System.out.println(b); 

Выходной сигнал -124

Почему это? Я знаю, что это очень простой вопрос, но я все еще не могу его сопоставить или понять, как это происходит?

В Java int – 32 бита. byte имеет 8 bits .

Большинство примитивных типов в Java подписаны, а byte , short , int и long кодируются в двух дополнениях. (Тип char имеет знака, а понятие знака не применимо к boolean .)

В этой схеме номера наиболее значимый бит указывает знак числа. Если требуется больше бит, самый старший бит («MSB») просто копируется в новый MSB.

Поэтому, если у вас есть байт 255 : 11111111 и вы хотите представить его как int (32 бита), вы просто копируете 1 влево 24 раза.

Теперь один из способов прочитать номер дополнения отрицательного двора – начать с младшего значащего бита, перемещаться влево, пока вы не найдете первый 1, а затем инвертируйте каждый бит впоследствии. Полученное число – это положительная версия этого числа

Например: 11111111 переходит в 00000001 = -1 . Это то, что Java будет отображать как значение.

То, что вы, вероятно, хотите сделать, это знать значение без знака байта.

Вы можете выполнить это с помощью битовой маски, которая удаляет все, кроме наименее значимых 8 бит. (0xff)

Так:

 byte signedByte = -1; int unsignedByte = signedByte & (0xff); System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte); 

Распечатал: "Signed: -1 Unsigned: 255"

Что на самом деле происходит здесь?

Мы используем побитовое И, чтобы замаскировать все посторонние знаковые биты (1 слева от наименее значимых 8 бит.) Когда int преобразуется в байт, Java прерывает самые левые 24 бита

 1111111111111111111111111010101 & 0000000000000000000000001111111 = 0000000000000000000000001010101 

Поскольку 32-й бит теперь является битом знака вместо 8-го бита (и мы установили бит знака равным 0, который является положительным), исходные 8 бит из байта считываются Java как положительное значение.

Чтобы понять, как это работает, нам нужно знать, что компьютеры работают в битах.

132 в базе 10 (десятичный) составляет 10000100 в базе 2 (двоичный). Поскольку Java хранит int в 32 битах, у нас есть

  00000000_00000000_00000000_10000100 

Когда int преобразуется в byte , Java прерывает самые последние 24 бит. Мы получаем 10000100 .

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

Если самый левый бит равен 1 (как здесь, здесь), это означает, что число отрицательно и требуется больше работы. Чтобы получить величину, мы минус один, затем применяем дополнение (применяем дополнение к нему, чтобы инвертировать биты):

  1. 10000100 – 1 = 10000011

  2. Инвертировать 10000011 = 01111100

01111100 при интерпретации десятичного числа – 124.

Таким образом, мы имеем отрицательное число с величиной 124, что дает нам -124 .

байт в Java подписан, поэтому он имеет диапазон от -2 ^ 7 до 2 ^ 7-1, т. е. от -128 до 127. Поскольку 132 превышает 127, вы обертываете вокруг 132-256 = -124. То есть, по существу, 256 (2 ^ 8) добавляется или вычитается до тех пор, пока он не попадает в диапазон.

Для получения дополнительной информации вы можете ознакомиться с дополнением двух .

132 находится вне диапазона байта, который составляет от -128 до 127 (Byte.MIN_VALUE – Byte.MAX_VALUE). Вместо этого верхний бит 8-битного значения обрабатывается как подписанный, что указывает на отрицательный результат в этом случае. Таким образом, число составляет 132 – 256 = -124.

часто в книгах вы найдете объяснение кастинга от int до байта как выполняемое модульным разделением. это не является строго правильным, как показано ниже, что фактически происходит, когда 24 наиболее значимых бита из двоичного значения номера int отбрасываются, оставляя путаницу, если установлен оставшийся самый левый бит, который обозначает число как отрицательное

 public class castingsample{ public static void main(String args[]){ int i; byte y; i = 1024; for(i = 1024; i > 0; i-- ){ y = (byte)i; System.out.print(i + " mod 128 = " + i%128 + " also "); System.out.println(i + " cast to byte " + " = " + y); } } } 

здесь очень механический метод без отвлекающих теорий:

  1. Преобразуйте число в двоичное представление (используйте калькулятор в порядке?)
  2. Скопируйте только самые правые 8 бит (LSB) и отбросьте остальные.
  3. Из результата шага №2, если крайний левый бит равен 0, используйте калькулятор для преобразования числа в десятичное. Это ваш ответ.
  4. Else (если самый левый бит равен 1), ваш ответ отрицательный. Оставьте все самые правые нули и первый ненулевой бит без изменений. И отменили остальные, т. Е. Заменили 1 на 0 и 0 на 1. Затем используйте калькулятор для преобразования в десятичную и добавьте отрицательный знак, чтобы указать, что значение отрицательное.

Этот более практичный метод соответствует многим теоретическим ответам выше. Итак, те, кто все еще читают эти Java-книги, говорящие, что используют modulo, это определенно неправильно, поскольку 4 шага, которые я изложил выше, определенно не являются модульной операцией.

Уравнение 2:

введите описание изображения здесь


В Java byte (N = 8) и int (N = 32) представлены приведенным выше 2s-дополнением.

Из уравнения a 7 отрицателен для byte но положителен для int .

 coef: a7 a6 a5 a4 a3 a2 a1 a0 Binary: 1 0 0 0 0 1 0 0 ---------------------------------------------- int: 128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = 132 byte: -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124 

Быстрый алгоритм, который имитирует способ его работы, следующий:

 public int toByte(int number) { int tmp = number & 0xff return (tmp & 0x80) == 0 ? tmp : tmp - 256; } 

Как это работает? Посмотрите на ответ daixtr . Реализация точного алгоритма, описанная в его ответе, такова:

 public static int toByte(int number) { int tmp = number & 0xff; if ((tmp & 0x80) == 0x80) { int bit = 1; int mask = 0; for(;;) { mask |= bit; if ((tmp & bit) == 0) { bit <<=1; continue; } int left = tmp & (~mask); int right = tmp & mask; left = ~left; left &= (~mask); tmp = left | right; tmp = -(tmp & 0xff); break; } } return tmp; } 

Концептуально повторяющиеся вычитания 256 выполняются на ваш номер, пока он не будет в диапазоне от -128 до +127. Таким образом, в вашем случае вы начинаете с 132, а затем получаете -124 за один шаг.

Вычислительно это соответствует извлечению 8 младших значащих бит из вашего исходного номера. (И обратите внимание, что самый старший бит этих 8 становится знаковым битом.)

Обратите внимание, что в других языках это поведение не определено (например, C и C ++).

  N is input number case 1: 0<=N<=127 answer=N; case 2: 128<=N<=256 answer=N-256 case 3: N>256 temp1=N/256; temp2=N-temp*256; if temp2<=127 then answer=temp2; else if temp2>=128 then answer=temp2-256; case 4: negative number input do same procedure.just change the sign of the solution 
  • не может статически ссылаться на нестатические поля
  • Обнаружение долгой печати с помощью Android
  • путь к файлу Windows в формате java
  • Удаление объекта в java?
  • READ_EXTERNAL_STORAGE разрешение для Android
  • как проверить Wi-Fi или 3g-сеть доступна на Android-устройстве
  • Как я могу печатать на одной строке?
  • Как поддерживать несколько версий Android в коде?
  • Как рисовать стрелку (в Android)?
  • ПРЕДУПРЕЖДЕНИЕ: невозможно изменить разрешения для всех:
  • Форма слишком большого исключения
  • Давайте будем гением компьютера.