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 我还尝试在Java中复制它们的哈希函数 |表示两组32位的分离,以便于可视化 #表示46位移位,包含18位,其中2位保留-ShardId ~表示36位移位,包含10位类型Id 其余36位-本地ID: #0000万#~00万~0000万|万|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
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);
}
}
shardId
值造成严重破坏。这一点,并确保他们被掩盖了。如果您决定在将来实现这2位,这也会有所帮助int
限制为32位。因为每个十六进制数字代表4位,所以在int
literal中最多可以有8个十六进制数字,但有9个F
s。您需要一个long
文本,通过追加L
localID
是36位,因此int
不足以保存所有可能的值,原因与上述相同。您的hash
方法应将localId
作为long
。当所需值为64位(along
)时,您可能需要将值强制转换为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
乍一看,这个值显然不适合Javaint
数据类型。因此,我们切换到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位(9x0xF
=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