Java int и long: как изменить самый значимый бит? - PullRequest
1 голос
/ 11 декабря 2011

Ради интереса, я реализую алгоритм DES в Java. (Ну, на самом деле это не так весело). В этом алгоритме вы обрабатываете блоки по 64 бита данных, и я подумал: эй, это прекрасно, давайте использовать «long» для хранения моих двоичных данных.

Затем я сталкиваюсь с серьезной проблемой, которая меня бесит: скажем, вы строите длинную, вот так:

long value = 785537;

Допустим, вы хотите установить для старшего значащего бита значение 1, вы бы сделали что-то вроде этого:

value |= 0x8000000000000000l;

Довольно просто, верно? Но это не работает вообще. У Java нет проблем с изменением другого бита, что означает, что

value |= 0x7000000000000000l;

будет работать. Но это не сработает, если это самый важный бит.

Почему? Есть ли способ добиться того, чего я хочу?

Заранее спасибо за ваши ответы.

Редактировать:

Вот пример кода, который я написал, для отображения long в двоичном виде:

public static void printBits(long input){
    StringBuilder builder = new StringBuilder();
    for(int i = 0; i < 64; i++){
        if((input & (0x1l << i)) != 0){
            builder.append('1');
        } else {
            builder.append('0');
        }
    }

    System.out.println(builder);
}

Если я сделаю это:

long val = -1;
printBits(val);

Он напечатает «1111111111111111111111111111111111111111111111111111111111111111111111111111111111111110», как и положено. Если я тогда наберу:

val |= Long.MIN_VALUE;
printBits(val);

Или

val |= 0x8000000000000000l;
printBits(val);

Это печать "111111111111111111111111111111111111111111111111111111111111111111111111111110" также ...

Если затем выполнить следующий тест:

(val & 8000000000000000l) != 0;

Это ложь ...

Ответы [ 2 ]

6 голосов
/ 11 декабря 2011

Это должно работать:

public class LongMsb {
  public static void main(String[] args) {
    long value = 785537;
    System.out.printf("%016x\n", value);
    value |= Long.MIN_VALUE;
    System.out.printf("%016x\n", value);
  }
}

Использование

value |= 0x8000000000000000l;

или

value |= 1L << 63;

вместо

value |= Long.MIN_VALUE;

также работает и, вероятно, более читабельно.

Оба печатают следующее:

00000000000bfc81
80000000000bfc81
0 голосов
/ 11 декабря 2011

Число, представленное старшим значащим битом, будет минимальным значением long, так что это будет:

long mask = Long.MIN_VALUE;

Затем, чтобы использовать эту маску для инвертирования старшего значащего бита, вы можете использовать битовый xor:

long value  = 785537;
value ^= mask;

РЕДАКТИРОВАТЬ: Я неправильно прочитал, я думал, что вы хотите инвертировать наиболее значимый бит; для простой установки ваш подход верен:

value |= mask;
...