Почему я не могу замаскировать 32 бита для длинного типа данных в Java - PullRequest
2 голосов
/ 28 апреля 2019

Я не могу понять, почему это работает. Я пытаюсь замаскировать 32 младших бита Java на длинном, но это не правильно И 33-й и 34-й бит и далее. Вот мой пример

class Main {
  public static void main(String[] args) {
    long someVal = 17592096894893l; //hex  0xFFFFAAFAFAD
    long mask = 0xFF; //binary
    long result = mask & someVal;                  

    System.out.println("Example 1 this works on one byte");
    System.out.printf("\n%x %s", someVal, Long.toBinaryString(someVal) );
    System.out.printf("\n%x %s", result, Long.toBinaryString(result) );

    long someVal2 = 17592096894893l; //hex  0xFFFFAAFAFAD
    mask = 0xFFFFFFFF; //binary
    result = mask & someVal2; 
    System.out.println("\nExample 2 - this does not work");
    System.out.printf("\n%x %s", someVal2, Long.toBinaryString(someVal2) );
    System.out.printf("\n%x %s", result, Long.toBinaryString(result) );
  }
}

Я ожидал, что результаты отбросят старший значащий байт до нуля, поскольку операция AND выполняла это на 32-битной системе. Вот вывод, который я получаю.

Example 1 - this works
ffffaafafad 11111111111111111010101011111010111110101101
ad 10101101
Example 2 - this does not work

ffffaafafad 11111111111111111010101011111010111110101101
ffffaafafad 11111111111111111010101011111010111110101101

Я бы хотел замаскировать первые 4 младших байта длинного значения.

1 Ответ

2 голосов
/ 28 апреля 2019

Я считаю, что вы видите здесь тот факт, что Java преобразует целые числа в длинные, используя расширение знака.

Для начала, что должен делать этот код?

int myInt = -1;
long myLong = myInt;
System.out.println(myLong);

Это должноинтуитивно распечатать -1, и это действительно так.Я имею в виду, было бы странно, если бы при преобразовании типа int в long мы не получили тот же номер, с которого начали.

Теперь давайте возьмем этот код:

int myInt = 0xFFFFFFFF;
long myLong = myInt;
System.out.println(myLong);

Что это печатает?Ну, 0xFFFFFFFF - это шестнадцатеричная версия подписанного 32-разрядного числа -1.Это означает, что этот код полностью эквивалентен приведенному выше коду, поэтому он должен (и должен) печатать одно и то же значение -1. ​​

Но значение -1, закодированное как long, не имеет представления0x00000000FFFFFFFF.Это будет 2 32 - 1, а не -1.Скорее всего, поскольку он длиной 64 бита, -1 представляется как 0xFFFFFFFFFFFFFFFFF.К сожалению, все верхние биты только что активированы!Это делает его не очень эффективным в качестве битовой маски.

Правило в Java состоит в том, что если вы преобразуете int в long, если самый первый бит в int равен 1, то все 32 старших бита longбудет установлен в 1, а также.Это так, что преобразование целого числа в длинное сохраняет числовое значение.

Если вы хотите создать битовую маску длиной 64 бита, инициализируйте ее длинным литералом, а не литералом int:

mask = 0xFFFFFFFFL; // note the L

Почему это имеет значение?Без L Java обрабатывает код как

  1. Создает целочисленное значение 0xFFFFFFFF = -1, давая 32 бита.
  2. Преобразует это целочисленное значение в long.Для этого используйте расширение знака, чтобы преобразовать его в длинное значение -1, давая 64 бита подряд.

Однако, если вы включите L, Java интерпретирует такие вещи как:

  1. Создайте длинное значение 0xFFFFFFFF = 2 32 - 1, которое представляет собой 32 нулевых бита, за которыми следуют 32 однобитных.
  2. Присвойте это значение маске.

Надеюсь, это поможет!

...