Упаковка 4 целых чисел в 64-битной длины - Java побитовый - PullRequest
0 голосов
/ 25 февраля 2010

Хорошо, у меня есть 4 целых числа, которые я хочу обернуть в длинный. Все 4 целых числа содержат 3 значения, расположенные в первых 2 байтах:

 +--------+--------+
 |xxpppppp|hdcsrrrr|
 +--------+--------+

{pppppp} представляет одно значение, {hdcs} представляет второе и {rrrr} последнее.

Я хочу собрать 4 из этих целых чисел в длинном. Я пробовал следующее:

ordinal = (c1.ordinal() << (14*3) | c2.ordinal() << (14*2) | c3.ordinal() << 14 | c4.ordinal());

где c1.ordinal () ... c4.ordinal () - целые числа для переноса.

Кажется, это не работает, если я запускаю тест. Допустим, я хочу посмотреть значения последнего целого числа в long, c4.ordinal(), где {pppppp} = 41, {hdcs} = 8 и {rrrr} = 14, я получаю следующие результаты:

System.out.println(c4.ordinal() & 0xf); //Prints 14
System.out.println(hand.ordinal() & 0xf); // Prints 14 - correct

System.out.println(c4.ordinal() >> 4 & 0xf); // Prints 8
System.out.println(hand.ordinal() >> 4 & 0xf); // Prints 8 - correct

System.out.println(c4.ordinal() >> 8 & 0x3f); // Prints 41
System.out.println(hand.ordinal() >> 8 & 0x3f); // Prints 61 - NOT correct!

Теперь следующее странно для меня. Если я уберу первые два целых числа и оберну только последние два, вот так:

ordinal = (c3.ordinal() << 14 | c4.ordinal());

И, запустив тот же тест, я получаю правильный результат:

System.out.println(c4.ordinal() >> 8 & 0x3f); // Prints 41
System.out.println(hand.ordinal() >> 8 & 0x3f); // Prints 41 - correct!

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

1 Ответ

6 голосов
/ 25 февраля 2010

Даже если вы присваиваете результат long, все операции выполняются со значениями int, и поэтому старшие биты теряются. Вынудите «повышение» к long, явно увеличив значения до long.

long ordinal = (long) c1.ordinal() << (14*3) | 
               (long) c2.ordinal() << (14*2) | 
               (long) c3.ordinal() <<    14  | 
               (long) c4.ordinal();

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

long ordinal = (c1.ordinal() & 0x3FFFL) << (14*3) | 
               (c2.ordinal() & 0x3FFFL) << (14*2) | 
               (c3.ordinal() & 0x3FFFL) <<    14  | 
               (c4.ordinal() & 0x3FFFL);
...