2016-03-29 5 views
1

В примере provided here,Бит маскирования неподписанные и подписанные значения

We created a 64 bit ID that contains the shard ID = 16 bit, the type of the containing data = 10 bit, and where this data is in the table (local ID) = 36.

The savvy additionology experts out there will notice that only adds to 62 bits. My past in compiler and chip design has taught me that reserve bits are worth their weight in gold. So we have two (set to zero).

Так это значит:

Вопрос один:

Они могут иметь 2^16, диапазон 0- 65536 осколков?

Идентификатор типа 2^10, диапазон 0-1024 типов?

Местный идентификатор 2^36, диапазон 0-68719476736 местных идентификаторов?

Кроме того, я пытаюсь повторить их хэш-функции в Java

| представляет собой разделение двух наборов из 32 бит, чтобы облегчить визуализацию.

# представляет собой битовый сдвиг 46, охватывающий 18 бит, из которых 2 зарезервированы - ShardId

~ представляет собой битовый сдвиг 36, заключающий 10 бит - Идентификатор типа Оставшихся 36 бит - локальный ID:

# 0000 0000 0000 0000 00 # ~ 00 0000 0000 ~ 0000 | 0000 0000 0000 0000 0000 0000 0000 0000 |


  1. Binary из ShardID 3429 = 1101 0110 0101
  2. Поэтому (hashedValue >> 46) = 00 0000 1101 0110 0101 &
  3. 0xFFFF = 1111 1111 1111 1111
  4. ShardId = 00 0000 1101 0110 0101

Вопрос второй:

Я понимаю, что нужно для 1. и 2. Однако я не понимаю, почему нам нужен побитовый оператор & 0xFFFF, поскольку 4 & 2 фактически одинаковы.

Вопрос третий:

Я получаю следующее сообщение об ошибке компилятора: Буквальный 0xFFFFFFFFF типа междунара вне диапазона

public class BitExampleTest { 
    public static void main(String[] args) { 
     long pinId = 241294492511762325L; 
     unHash(pinId); 
    } 

    private static long hash(int shardId, int typeId, int localId){ 
     return (shardId << 46) | (typeId << 36) | (localId << 0); 
    } 

    private static void unHash(long hashedValue){ 
       long shardID = (hashedValue >> 46) & 0xFFFF; 
       long typeID = (hashedValue >> 36) & 0x3FF; 
       long localID = (hashedValue >> 0) & 0xFFFFFFFFF; 

       System.out.printf("shardID %s \n",shardID); 
       System.out.printf("typeID %s \n",typeID); 
       System.out.printf("localID %s \n",localID); 
    } 
} 
+0

Q3: используйте буквенный длинный суффикс: '0xFFFFFFFFFL'. –

+0

Очень интересно, что у SO не было подробного сообщения о бит-масках. +1 от меня –

+0

Здесь нет «хеширующих значений». Все входные данные присутствуют на выходе. – EJP

ответ

1

They can have 2^16, range of 0-65536 shards?

Осколок ID - 16 бит. Итак, 2 возможны разные Осколки.

Type ID of 2^10, range of 0-1024 types?

Идентификатор типа 10 бит. Итак, 2 возможны различные идентификаторы типа.

Local ID of 2^36, range of 0-68719476736 local id's?

Местный идентификатор - 36 бит. Таким образом, 2 Возможны различные локальные идентификаторы, то есть указатели на 2 Возможны местоположения в таблице.

Теперь, ссылаясь на Pinterest post, Пин идентификатор, используемый для демонстрации является 241294492511762325.

На первый взгляд, очевидно, что это значение не будет соответствовать в Java int типа данных. Итак, мы переходим к long.

// 'L' added to tell the compiler it is a long, not an int 
System.out.println(Long.toBinaryString(241294492511762325L)); 

// output (padded with 0's on the left) 
0000 0011 0101 1001 0100 0000 0001 0000 0000 0000 0110 1011 1111 0111 1001 0101 

Первоначально идентификатор 241294492511762325 выглядит так ...

xx 00 0011 0101 1001 01 00 0000 0001 0000 0000 0000 0110 1011 1111 0111 1001 0101 
XX [____SHARD(16)_____] [_TYPE(10)_] [________________LOCAL(36)_________________] 

Чтобы получить осколок биты, сдвигают вправо ID по формуле (10 + 36) 46 будет работать. Это нас привлечет. Пожалуйста, обратите внимание, что биты слева от XX могут быть либо 0-й или 1, в зависимости от знака расширения из «последних двух бит» и т.д.

xx 00 0011 0101 1001 01 
XX [____SHARD(16)_____] 

Принимая побитовый И это с 0xffff

  'our 2 golden bits' 
        ▼▼ 
    xxxx xxxx xxxx xxxx 0000 1101 0110 0101 
& 0000 0000 0000 0000 1111 1111 1111 1111 
= 0000 0000 0000 0000 0000 1101 0110 0101 

Независимо от того, для чего были установлены ведущие биты, теперь они все 0. Я думаю, это должно разъяснить вам причину побитового И с 0xffff. Если они оставлены с добавлением 0, отлично. Если они не являются И заботится об этом. :)

Когда вы инициализируете литерал как 0xFFFFFFFFF, если нет суффикса, а переменная является интегральным типом (int, long и т. Д.), Предполагается, что значение равно int. И, int может содержать 32 бита, а не 36 бит (9 x 0xF = 9 x '1111'), как вы пытаетесь. Таким образом, вы должны использовать long, который имеет емкость 64 бит. Добавление «L» или «l» в конец значения, например 0xFFFFFFFFFL, должно заботиться об ошибке компилятора.[Reference]

0
  1. Да, ваши диапазоны являются правильными, за исключением того, что максимум 2 n - 1.

  2. Те последние 2 би ts («стоит их вес в золоте») может привести к хаосу с shardId значением, если его игнорировать. Этот бит - и гарантирует, что они замаскированы. Это также помогает, если вы решите реализовать эти 2 бита в будущем.

  3. Тип int в Java ограничен 32 битами.Поскольку каждая шестнадцатеричная цифра представляет 4 бита, вы можете иметь максимум 8 шестнадцатеричных цифр в литерале int, но у вас есть 9 F s. Вам нужен литерал long, добавив L.

long localID = (hashedValue >> 0) & 0xFFFFFFFFFL; 

, потому что ваш localID составляет 36 битов, int недостаточно, чтобы вместить все возможные значения, по той же причине, что и выше. Ваш метод hash должен принимать localId как long. Возможно, вам нужно будет указать свои значения как long перед их смещением влево, чтобы избежать интерпретации как int, когда желаемое значение составляет 64 бит (a long).

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