位掩码无符号和有符号值

时间:2016-03-29 21:28:43

标签: java

在示例provided here中,

  

我们创建了一个64位ID,其中包含分片ID = 16位的类型   包含数据= 10位,以及此数据在表中的位置   (当地身份证)= 36.

     

那里精明的额外学专家会注意到只会增加   到62位。我在编译器和芯片设计方面的过去教会了我   储备位在黄金上是值得的。所以我们有两个(设置为   零)。

这是否意味着:

问题一:

他们可以有2 ^ 16,范围为0-65536分片?

类型ID为2 ^ 10,范围为0-1024种类型?

本地ID为2 ^ 36,范围为0-68719476736本地ID'

我也试图在Java中复制他们的散列函数

|表示两组32位的分离,以便于可视化。

#代表46位移位,其中18位保留2位 - ShardId

〜表示36位的位移,包含10位 - 类型Id 剩下的36位 - 本地ID:

<00>#0000 0000 0000 0000 00#〜00 0000 0000~0000 | 0000 0000 0000 0000 0000 0000 0000 0000 |

  1. ShardID二元3429 = 1101 0110 0101
  2. 因此(hashedValue&gt;&gt; 46)= 00 0000 1101 0110 0101 &安培;
  3. 0xFFFF = 1111 1111 1111 1111
  4. ShardId = 00 0000 1101 0110 0101
  5. 问题二:

    我理解需要1.和2.但我不明白为什么我们需要一个按位运算符&amp; 0xFFFF自4&amp; 2实际上是一样的。

    问题三:

    我得到以下编译器错误:int类型的文字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);
        }
    }
    

2 个答案:

答案 0 :(得分:1)

  

他们可以有2 ^ 16,范围为0-65536分片?

Shard ID为16位。因此,2 16 不同的Shard ID是可能的。

  

类型ID为2 ^ 10,范围为0-1024种类型?

类型ID是10位。因此,2 10 不同的类型ID是可能的。

  

本地ID为2 ^ 36,范围为0-68719476736本地ID?

本地ID为36位。因此,2 36 不同的本地ID是可能的,即表中的2 36 位置的指针是可能的。

现在,参考Pinterest post,用于演示的Pin ID为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的ID看起来像这样......

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)_________________]

要获得Shard位,右移ID(10 + 36)46将起作用。这会得到我们。请注意,XX左侧的位可以是0或1,具体取决于“最后两位”的符号扩展等。

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

使用0xffff

进行逐位AND
           '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的按位AND背后的原因。如果它们用0表示左边填充,那很好。如果他们不是AND照顾它。 :)

初始化像0xFFFFFFFFF这样的文字时,如果没有后缀且变量是整数类型(int,long等),则该值假定为int。并且,int可以保存32位,而不是36位(9 x 0xF = 9 x '1111'),就像您正在尝试的那样。因此,您必须使用容量为64位的long。在值的末尾附加'L'或'l',如0xFFFFFFFFFL,应该处理编译器错误。 [Reference]

答案 1 :(得分:0)

  1. 是的,您的范围是正确的,但最大值是2 n - 1。

  2. 那些最后的2位(&#34;值得他们在黄金中的重量&#34;)如果被忽略可能会导致shardId值的破坏。这个位 - 并确保它们被屏蔽掉。如果您决定在将来实施这两个位,这也会有所帮助。

  3. Java中的int类型限制为32位。因为每个十六进制数字代表4位,所以int字面值中最多可包含8个十六进制数字,但您有9 F个。您需要long字面值,方法是附加L

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

    由于localID为36位,int不足以容纳所有可能的值,原因与上述相同。您的hash方法应将localId作为long。您可能需要将值转换为long,然后将它们向左移位以避免解释为int,此时所需的值为64位(long)。