Можем ли мы сделать unsigned byte в Java?

Я пытаюсь преобразовать подписанный байт в unsigned. Проблема заключается в том, что данные, которые я получаю, являются неподписанными, а Java не поддерживает байты без знака, поэтому, когда он считывает данные, они обрабатывают его как подписанные.

Я попробовал преобразовать его по следующему решению, которое я получил из Stack Overflow.

public static int unsignedToBytes(byte a)
{
    int b = a & 0xFF;
    return b;
}

Но когда он снова преобразуется в байт, я получаю одинаковые подписанные данные. Я пытаюсь использовать эти данные в качестве параметра для функции Java, которая принимает только байт как параметр, поэтому я не могу использовать какой-либо другой тип данных. Как я могу исправить эту проблему?

Ответ 1

Я не уверен, что понимаю ваш вопрос.

Я просто попробовал это, и для байта -12 (знаковое значение) он возвращал целое число 244 (эквивалентное значению без знакового байта, но вводимое как int):

  public static int unsignedToBytes(byte b) {
    return b & 0xFF;
  }

  public static void main(String[] args) {
    System.out.println(unsignedToBytes((byte) -12));
  }

Это то, что вы хотите сделать?

Java не позволяет выразить 244 как значение byte, как и C. Чтобы выразить положительные целые числа выше Byte.MAX_VALUE (127), вам нужно использовать другой целочисленный тип, например short, int или long.

Ответ 2

Тот факт, что примитивы подписаны на Java, не имеет отношения к тому, как они представлены в памяти/транзите - байт - всего 8 бит, и понимаете ли вы это как подписанный диапазон или нет, зависит от вас. Нет волшебного флага, чтобы сказать "это подписан" или "это без знака".

Когда примитивы подписаны, компилятор Java не позволит вам присвоить значение выше +127 байту (или ниже -128). Тем не менее, нет ничего, что могло бы помешать вам превзойти int (или короткое), чтобы достичь этого:

int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200)
byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention)

/*
 * Will print a negative int -56 because upcasting byte to int does
 * so called "sign extension" which yields those bits:
 * 1111 1111 1111 1111 1111 1111 1100 1000 (-56)
 *
 * But you could still choose to interpret this as +200.
 */
System.out.println(b); // "-56"

/*
 * Will print a positive int 200 because bitwise AND with 0xFF will
 * zero all the 24 most significant bits that:
 * a) were added during upcasting to int which took place silently
 *    just before evaluating the bitwise AND operator.
 *    So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`.
 * b) were set to 1s because of "sign extension" during the upcasting
 *
 * 1111 1111 1111 1111 1111 1111 1100 1000 (the int)
 * &
 * 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF)
 * =======================================
 * 0000 0000 0000 0000 0000 0000 1100 1000 (200)
 */
System.out.println(b & 0xFF); // "200"

/*
 * You would typically do this *within* the method that expected an 
 * unsigned byte and the advantage is you apply `0xFF` only once
 * and than you use the `unsignedByte` variable in all your bitwise
 * operations.
 *
 * You could use any integer type longer than `byte` for the `unsignedByte` variable,
 * i.e. `short`, `int`, `long` and even `char`, but during bitwise operations
 * it would get casted to `int` anyway.
 */
void printUnsignedByte(byte b) {
    int unsignedByte = b & 0xFF;
    System.out.println(unsignedByte); // "200"
}

Ответ 3

В Java нет примитивных байтов без знака. Обычная вещь - бросить ее на больший тип:

int anUnsignedByte = (int) aSignedByte & 0xff;

Ответ 4

Язык Java не предоставляет ничего подобного ключевому слову unsigned. A byte в соответствии с спецификацией языка представляет значение между & min 128: 127. Например, если a byte передается в int Java будет интерпретировать первый бит как знак и использовать расширение знака.

Тем не менее, ничто не мешает вам просматривать byte просто как 8 бит и интерпретировать эти биты как значение от 0 до 255. Просто имейте в виду, что вы ничего не можете сделать, чтобы заставить вашу интерпретацию другим методом, Если метод принимает byte, тогда этот метод принимает значение между & минус 128 и 127, если явно не указано иначе.

Вот несколько полезных преобразований/манипуляций для вашего удобства:

Преобразования в/из int

// From int to unsigned byte
int i = 200;                    // some value between 0 and 255
byte b = (byte) i;              // 8 bits representing that value

// From unsigned byte to int
byte b = 123;                   // 8 bits representing a value between 0 and 255
int i = b & 0xFF;               // an int representing the same value

(Или, если вы используете Java 8+, используйте Byte.toUnsignedInt.)

Разбор/форматирование

Лучший способ - использовать приведенные выше преобразования:

// Parse an unsigned byte
byte b = (byte) Integer.parseInt("200");

// Print an unsigned byte
System.out.println("Value of my unsigned byte: " + (b & 0xFF));

Арифметика

Представление с двумя дополнениями "просто работает" для сложения, вычитания и умножения:

// two unsigned bytes
byte b1 = (byte) 200;
byte b2 = (byte) 15;

byte sum  = (byte) (b1 + b2);  // 215
byte diff = (byte) (b1 - b2);  // 185
byte prod = (byte) (b2 * b2);  // 225

Раздел требует ручного преобразования операндов:

byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));

Ответ 5

Я думаю, что другие ответы охватывали представление памяти, и как вы справляетесь с этим, зависит от контекста того, как вы планируете его использовать. Я добавлю, что Java 8 добавила некоторую поддержку для работы с неподписанными типами. В этом случае вы можете использовать Byte.toUnsignedInt

int unsignedInt = Byte.toUnsignedInt(myByte);

Ответ 6

Примечание, если вы хотите распечатать его, вы можете просто сказать

byte b = 255;
System.out.println((b < 0 ? 256 + b : b));

Ответ 7

Адамски дал лучший ответ, но он не совсем завершен, поэтому прочитайте его ответ, так как он объясняет детали, которые я не знаю.

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

Итак, если системная функция требует четырех байтов, например 192 168 0 1 в качестве неподписанных байтов, вы можете передать -64 -88 0 1, и функция все равно будет работать, потому что акт передачи их функции будет un -Измените их.

Однако у вас вряд ли будет такая проблема, поскольку системные функции скрыты за классами для кросс-платформенной совместимости, хотя некоторые из методов чтения java.io возвращают неиспользуемые байты как int.

Если вы хотите увидеть это, попробуйте записать подписанные байты в файл и прочитать их как неподписанные байты.

Ответ 8

Если у вас есть функция, которая должна быть передана подписанным байтом, что вы ожидаете от нее, если вы передаете беззнаковый байт?

Почему вы не можете использовать какой-либо другой тип данных?

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

Ответ 9

Хотя это может показаться раздражающим (исходящим из C), что Java не включала беззнаковый байт в язык, это действительно не имеет большого значения, поскольку простая операция "b и 0xFF" дает неподписанное значение для (подписанного) байта b в (редких) ситуациях, в которых это действительно необходимо. Биты фактически не изменяются - просто интерпретация (что важно только при выполнении, например, некоторых математических операций над значениями).

Ответ 10

Если вы думаете, что ищете что-то вроде этого.

public static char toUnsigned(byte b) {
    return (char) (b >= 0 ? b : 256 + b);
}

Ответ 11

В Java нет байта без знака, но если вы хотите отобразить байт, вы можете сделать,

int myInt = 144;

byte myByte = (byte) myInt;

char myChar = (char) (myByte & 0xFF);

System.out.println("myChar :" + Integer.toHexString(myChar));

Вывод:

myChar : 90

Для получения дополнительной информации, пожалуйста, проверьте Как отобразить значение hex/byte в Java.

Ответ 12

В соответствии с ограничениями в Java, неподписанный байт практически невозможен в текущем формате типа данных. Вы можете использовать некоторые другие библиотеки другого языка для того, что вы реализуете, а затем вы можете их вызвать, используя JNI.

Ответ 13

Если вы хотите беззнаковые байты в Java, просто вычтите 256 из интересующего вас числа. Он произведет два дополнения с отрицательным значение, которое является желаемым числом в неподписанных байтах.

Пример:

int speed = 255; //Integer with the desired byte value
byte speed_unsigned = (byte)(speed-256);
//This will be represented in two complement so its binary value will be 1111 1111
//which is the unsigned byte we desire.

Вам нужно использовать такие грязные хаки при использовании leJOS для программирования Кирпич NXT.

Ответ 14

Да и нет. Я искал эту проблему. Как я понимаю это:

Дело в том, что java подписала interger -128 до 127.. В java можно представить без знака:

public static int toUnsignedInt(byte x) {
    return ((int) x) & 0xff;
}

Если вы, например, добавили номер -12 подписанного числа без знака, вы получите 244. Но вы можете снова использовать это число в подписанном, его нужно переместить обратно в подписанное, и он снова будет12.

Если вы попытаетесь добавить 244 в java-байт, вы получите outOfIndexException.

Приветствия..