Java 位屏蔽无符号和有符号值

Java 位屏蔽无符号和有符号值,java,Java,在这个例子中 我们创建了一个64位的ID,其中包含shard ID=16位的类型 包含数据的长度=10位,并且该数据在表中的位置 (本地ID)=36 精明的加法学专家会注意到,只有 到62位。我在编译器和芯片设计方面的经历教会了我这一点 储备比特的黄金价值相当于它们的重量。所以我们有两个(设置为 零) 这是否意味着: 问题一: 它们可以有2^16个,范围为0-65536个碎片 类型ID为2^10,范围为0-1024个类型 本地ID为2^36,范围为0-68719476736本地ID 我还尝试在J

在这个例子中

我们创建了一个64位的ID,其中包含shard ID=16位的类型 包含数据的长度=10位,并且该数据在表中的位置 (本地ID)=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:

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


  • ShardID 3429的二进制代码=1101 0110 0101
  • 因此(hashedValue>>46)=00 0000 1101 0110 0101 &
  • 0xFFFF=1111111111111111111
  • ShardId=00 0000 1101 0110 0101
  • 问题二:

    我明白需要1。二,。但是我不明白为什么我们需要一个位运算符&0xFFFF,因为4和2实际上是相同的

    问题三:

    我收到以下编译器错误:int类型的文本0xFFFFFFFFFFF超出范围

    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);
        }
    }
    
    公共类BitExampleTest{
    公共静态void main(字符串[]args){
    长pinId=241294492511762325L;
    unHash(pinId);
    }
    私有静态长哈希(int shardId、int typeId、int localId){
    返回(shardId>36)&0x3FF;
    long localID=(hashedValue>>0)&0xFFFFFFFFF;
    System.out.printf(“shardID%s\n”,shardID);
    System.out.printf(“类型ID%s\n”,类型ID);
    System.out.printf(“localID%s\n”,localID);
    }
    }
    
  • 是的,你的范围是正确的,只是最大值是2n-1

  • 如果忽略最后的2位(“相当于黄金的重量”),可能会对
    shardId
    值造成严重破坏。这一点,并确保他们被掩盖了。如果您决定在将来实现这2位,这也会有所帮助

  • Java中的类型
    int
    限制为32位。因为每个十六进制数字代表4位,所以在
    int
    literal中最多可以有8个十六进制数字,但有9个
    F
    s。您需要一个
    long
    文本,通过追加
    L

  • 由于您的
    localID
    是36位,因此
    int
    不足以保存所有可能的值,原因与上述相同。您的
    hash
    方法应将
    localId
    作为
    long
    。当所需值为64位(a
    long
    )时,您可能需要将值强制转换为
    long
    ,然后再将其向左移位,以避免解释为
    int

    它们可以有2^16个,范围为0-65536个碎片

    碎片ID为16位。因此,216个不同的碎片ID是可能的

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

    类型ID为10位。因此,210个不同类型的ID是可能的

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

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

    现在,参考,用于演示的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)_________________]
    
    为了获得碎片位,将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背后的原因。如果它们用0填充,那就太好了。如果他们不是最重要的人,他们会照顾好它。:)


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

    Q3:使用文字长后缀:
    0xfffffffl
    。非常有趣的是,SO没有深入讨论位掩码+这里没有“散列值”。所有输入数据都存在于输出中。
               '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