int i =132;
byte b =(byte)i;
System.out.println(b);
Выходной сигнал -124
Почему? Я знаю, что это очень простой вопрос, но я все еще не могу его сопоставить или понять, как это происходит?
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 в base 10 (десятичный) 10000100
в base 2 (двоичный код). Поскольку Java хранит int
в 32 битах, мы имеем
00000000_00000000_00000000_10000100
Когда int
преобразуется в byte
, Java прерывает самые последние 24 бита. Мы получаем 10000100
.
В два дополнения, самый левый бит используется как знак. Если самый левый бит 0
, ничего больше не будет сделано.
Если самый левый бит 1
(как мы здесь имеем), это означает, что число отрицательно и требуется больше работы. Чтобы получить величину, мы минус один, затем применим один дополнительный вариант (примените одно дополнение означает, что мы инвертируем бит):
10000100
- 1 = 10000011
Инвертировать 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.
здесь очень механический метод без отвлекающих теорий:
Этот более практичный метод соответствует многим теоретическим ответам выше. Итак, те, кто все еще читают эти Java-книги, говорящие, что используют modulo, это определенно неправильно, поскольку 4 шага, которые я изложил выше, определенно не являются модульной операцией.
В 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
часто в книгах вы найдете объяснение кастинга от 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);
}
}
}
Быстрый алгоритм, который имитирует способ его работы, следующий:
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 и С++).
Если вы хотите понять это математически, например, как это работает
так что в основном числа от ч/б -128 до 127 будут записываться так же, как их десятичное значение, выше его (ваше число - 256).
например. 132, ответ будет 132 - 256 = - 124 т.е.
256 + ваш ответ на число 256 + (-124) составляет 132
Другой пример
double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);
Выход будет 39 44
(295 - 256) (300 - 256)
ПРИМЕЧАНИЕ: он не будет учитывать числа после десятичной дроби.
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