Каков наиболее эффективный способ в Java для подписи расширения произвольной длины битов? - PullRequest
0 голосов
/ 13 февраля 2019

Скажем, например, я упаковал три 10-битных целых числа со знаком в целое число Java.

Я могу легко извлечь 10 битов:

int unpacked = packed & 0x3FF;
packed >>= 10;
etc ...

Но теперь мне нужнознак расширяет верхний бит (бит 9 справа).Есть ли быстрый способ сделать это, прибегнув к тестированию старшего бита и настройке?

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

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Альтернативой сдвигу в два раза является переворачивание знака с последующим его вычитанием:

int unpacked = packed & 0x3FF;
int extended = (unpacked ^ 0x200) - 0x200;

Если знак не был установлен, его переворачивание устанавливает его, а вычитание сбрасывает его снова.

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

Это имеет некоторые преимущества,

  • Код не зависит от размера целевого целочисленного типа, если бы unpacked и extended были long, то то же самое сработало бы.
  • XOR и вычитание могут быть немного дешевлеНапример, на Skylake вы можете выполнять 4 из этих основных операций за цикл, но только 2 смены.Однако задержка такая же, и она имеет значение, только если доступный ILP в коде высок.
  • Сдвиги на самом деле не алгебраически объединяются, но XOR и вычитание могут.Например, если следующая операция заключается в добавлении некоторой константы к extended, то это сложение и шаги «вычесть знак» можно объединить в одну операцию.
0 голосов
/ 13 февраля 2019
int signed = (packed << (32 - 10)) >> (32 - 10);

Поскольку >>> - это беззнаковое смещение вправо, а >> - подписанное смещение вправо.

(у меня все еще была ошибка, спасибо @rghome)

...