2012-05-28 2 views
0

Чтобы преобразовать Int в массив байтов, я использую следующий код:Java - преобразование Int в массив байтов без учета знака

int a = 128; 
byte[] b = convertIntValueToByteArray(a); 
private static byte[] convertIntValueToByteArray(int intValue){ 
    BigInteger bigInteger = BigInteger.valueOf(intValue); 
    byte[] origByteArray = bigInteger.toByteArray(); 
    byte[] noSignByteArray = new byte[bigInteger.bitLength()/8]; 

    if(bigInteger.bitLength()%8!=0){ 
    noSignByteArray = origByteArray; 
    }else{ 
    System.arraycopy(origByteArray,1,noSignByteArray,0,noSignByteArray.length); 
    } 

    return noSignByteArray; 
} 

Есть две вещи, которые я пытаюсь сделать.

1) Мне нужно знать количество байтов (округленное до закрывающего байта) исходного целого числа. Тем не менее, мне не нужен дополнительный бит, который добавляется для бита знака, когда я вызываю метод toByteArray(). Вот почему у меня есть вспомогательный метод. Поэтому в этом примере, если у меня нет вспомогательного метода, когда я конвертирую 128 в массив байтов, я получаю длину 2 октета из-за знакового бита, но я ожидаю, что это будет один октет.

2) Мне нужно положительное представление числа. В этом примере, если я попытаюсь напечатать первый элемент в массиве b, я получаю -128. Однако числа, которые я буду использовать, будут только положительными числами, так что я действительно хочу 128. Я ограничен использованием байтового массива. Есть ли способ сделать это?

Обновлено сообщение

Спасибо за ответы. Я не нашел точного ответа, который я искал, поэтому я попытаюсь дать более подробную информацию. В конечном счете, я хочу писать значения разных типов по потоку вывода данных. В этом сообщении я хотел бы уточнить, что происходит, когда ints записываются в поток вывода данных. Я столкнулся с двумя сценариями.

1)

DataOutputStream os = new DataOutputStream(this.socket.getOutputStream()); 

byte[] b = BigInteger.valueOf(128).toByteArray(); 

os.write(b); 

2)

DataOutputStream os = new DataOutputStream(this.socket.getOutputStream()); 
os.write(128); 

В первом сценарии, когда байты считываются из входного потока данных, кажется, что первый элемент в массиве является 0 для представления msb, а второй элемент в массиве содержит номер -128. Однако, поскольку msb равен 0, мы могли бы определить, что оно должно быть положительным числом. Во втором сценарии нет msb, и единственный элемент, присутствующий в массиве байтов, считанный из входного потока, равен -128. Я ожидал, что метод write() выходного потока данных преобразует int в массив байтов таким же образом, как метод toByteArray() для объекта BigInteger. Однако, похоже, это не так, поскольку msb нет. Поэтому мой вопрос заключается в том, как во втором сценарии мы должны знать, что 128 должно быть положительным числом, а не отрицательным, если нет msb.

+0

Подписанный '' byte '' не может представлять число 128. Вы можете сопоставить отрицательные числа положительным числам с помощью некоторой пользовательской функции в момент, когда вы читаете значения из массива. –

+0

@MarkoTopolnik: Упс, мозговой пердит. :п – Amadan

ответ

4

Как вы, наверное, уже знаете

  • В октета, шаблон 10000000 может быть интерпретировано как либо 128 или -128, в зависимости от того, гм, вне интерпретации
  • Явы byte типа интерпретирует octects как значения только в -128 ... 127.

Если вы создаете приложение, в котором весь мир состоит из неотрицательных целых чисел только, то вы могли бы просто сделать все ваши работы в предположении, что значение байта -128 будет означать 128 и -127 будет среднее значение 129 и ... и -1 будет означать 255. Это, безусловно, выполнимо, но оно требует работы.

Работа с понятием «байт без знака», как это обычно делается путем расширения байта в short или int с высшими битами порядка весь набор до нуля, а затем выполнять арифметические операции или отображения ваших значений. Вам нужно будет решить, подходит ли такой подход по своему вкусу, чем просто представлять 128 как два октета в вашем массиве.

2

Я думаю, что следующего кода может быть достаточно.

В Java INT является двойками-дополняет двоичное число:

-1    = 111...111 
ones complement = 000...000; + 1 = 
1    = 000...001 

Так что о знаковом бите я не понимаю. Будь то, что ты мог бы сделать Math.abs(n). A байт варьируется от -128 до 127, но интерпретация является вопросом маскировки, как показано ниже.

public static void main(String[] args) { 
    int n = 128; 

    byte[] bytes = intToFlexBytes(n); 
    for (byte b: bytes) 
     System.out.println("byte " + (((int)b) & 0xFF)); 
} 

public static byte[] intToFlexBytes(int n) { 
    // Convert int to byte[4], via a ByteBuffer: 
    byte[] bytes = new byte[4]; 
    ByteBuffer bb = ByteBuffer.allocateDirect(4); 
    bb.asIntBuffer().put(n); 
    bb.position(0); 
    bb.get(bytes); 

    // Leading bytes with 0: 
    int i = 0; 
    while (i < 4 && bytes[i] == 0) 
     ++i; 

    // Shorten bytes array if needed: 
    if (i != 0) { 
     byte[] shortenedBytes = new byte[4 - i]; 
     for (int j = i; j < 4; ++j) { 
      shortenedBytes[j - i] = bytes[j]; // System.arrayCopy not needed. 
     } 
     bytes = shortenedBytes; 
    } 
    return bytes; 
} 
1

Чтобы ответить на ваш первый вопрос, сколько байтов требуется представлять неотрицательное целое число без знака, используя представление, рассмотрим следующие функции, которые я написал в Common Lisp.

(defconstant +bits-per-byte+ 8) 

(defun bit-length (n) 
    (check-type n (integer 0) "a nonnegative integer") 
    (if (zerop n) 
     1 
     (1+ (floor (log n 2))))) 

(defun bytes-for-bits (n) 
    (check-type n (integer 1) "a positive integer") 
    (values (ceiling n +bits-per-byte+))) 

Они подчеркивают математические основы задачи: а именно, logarithm говорит вам, сколько сила два (как это предусмотрено в битах) он принимает доминировать заданное неотрицательное целое число, скорректированное быть ступенчатой ​​функцией с floor , и количество байтов, которое требуется для того, чтобы снова удерживать это число бит в качестве ступенчатой ​​функции, на этот раз с ceiling.

Обратите внимание на то, что числовое значение в качестве входного сигнала для функции логарифма является недопустимым, поэтому мы избегаем его явно. Вы можете заметить, что функция bit-length также может быть написана с легким преобразованием выражения ядра:

(defun bit-length-alt (n) 
    (check-type n (integer 0) "a nonnegative integer") 
    (values (ceiling (log (1+ n) 2)))) 

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

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

Смежные вопросы