雪花算法(02)算法中的位运算

前面介绍了雪花算法的理论基础,可以对大概的算法有个了解,但是细节上可能还是模糊,下面来说一下雪花算法中用到的位运算。这里先介绍两个,一个是:

<<

一个是

|

<<的作用是将数字向左移动,这里的数字指的是二进制中的数,并不是字面上的长整型数字,当然移动后数字字面值肯定发生变化,但是这里对这个操作的主要理解要放在二进制数字向左移动上,而不是字面值扩大2的n次方倍。

“|” 的作用是或运算,两个数对应的位上只要有一个是1就是1,这样的官方解释不太明显,放在雪花算法中的作用就是合并数字,下面会详细演示。也就是说,三个需要生成的部分,分别由三个数来生成,然后利用 <<往左移动到对应的位置,最后将三个数字用 | 合并。这就是雪花算法中两个位移操作的作用。

介绍一个例子比如有三个数字,分别打印出这三个数字的二进制形式:

可以看到,5对应的二进制就是101,8对应的2进制就是1000,10对应的二进制就是1010。这三个数字转换成二进制后,所有的0和1自然还是在最右边的末尾,下面就来进行位移操作a向左移动20位,b向左移动10位,c不变:

通过a和b位移结果的前后对比,可以发现在二进制的形式下,位移操作的意义浅显易懂,就是把代表值的所有数字向左移动了对应的位数。我们把雪花算法生成的数字也分成了三部分,这三部分可以分别按照规则生成,然后用<<操作向左移动对应的位数,就可以到达对应的位置,最后再合并即可。

来看一下合并的代码:

上面的“a|b|c”操作就是合并三个数字,怎么合并呢?就是多个64位的数字对应的合在一起,在这64中,只要对应位数上有一个位置是1,合并后这个位上的数字就是1,否则就是0,根据这个结果,我们看到数字d的二进制形式确实包含了abc三个的所有数字。虽然最后的结果d是一个难以猜到的数字,但是我们进行位运算一定要看二进制,不要看整数字面值,这三个数字放在了各自对应的位数范围内,只要三个数字的范围不越界,也就是说a永远在从右向左20位以后,b永远在10到20之间,c永远在0到10之间,那么这三个数字就可以各管各的,并且结果是合法合理的。

当然这种操作也是有底线的,比如b,他的数字大小转换成2进制后如果长度比10位大,那么它就会和a互相影响,导致结果不可预料,这就是范围的由来。我们再来考虑一下雪花算法,除了第一位0之外,第一部分是时间部分,占41位,也就是说生成的时间数字要向左移动(64-1-41=)22位,第二部分是机器信息,占10位,也即是说代表机器信息的数字生成后要向左移动(64-1-41-10=)12位,当然第三部分在末尾,就不用位移了。这三部分计算出来并且向左位移完成后,直接用“|”运算合成即可,就是我们最终要的分布式唯一id。

代码地址:https://gitee.com/blueses/snowflake-demo 02

原文地址:https://www.cnblogs.com/guos/p/11351404.html

时间: 2024-11-09 08:13:14

雪花算法(02)算法中的位运算的相关文章

关于c语言中的位运算。。。

位运算是一种针对二进制数的一种运算 位运算 共有六种 都有其对应得操作符号 &      (and)      位于 |        (or)         位或 ~      (not)        取反 ^       (xor)        异或 >>    (shr)    右移一位 <<    (shl)     左移一位 运算说明: === 1. and运算 === and运算通常用于二进制取位操作,例如一个数 and 1的结果就是取二进制的最末位.这可

C#位运算示例和enum中的位运算

今天在项目中遇到按位或组合权限串的问题: 首先每一个权限数都是2的N次方数 如:k1=2 ; //添加 k2=4 ; //删除 k3=8; //修改 ... 如此定义功能权限数,当需要组合权限时,就需要对各个所拥有的权限数按位或了. 如: purview = k2|k3; // 赋给添加和删除权限 当需要判断在权限串中是否拥有某一权限时,就需要进行按位与. 如: if((purview & k1) >0)//判断此权限串是否拥有添加权限,结果>0 则进入if语句代码块中 { ....

枚举中的位运算

为什么枚举中位运算都可以使用并运算? 1.  什么是枚举中的位运算? 例如 int a = 1 << 0; //1左移0位    1*2^0 = 1; int b = 1 << 1; //1左移1位   1*2^1 = 2; int c = 1 << 2; //1左移2位   1*2^2 = 4; int d = 1 << 3; //1左移3位   1*2^3 = 8; 并运算 a | b 01 10 -------------- 11 ==1+2 int

深入研究js中的位运算及用法

什么是位运算? 位运算是在数字底层(即表示数字的 32 个数位)进行运算的.由于位运算是低级的运算操作,所以速度往往也是最快的(相对其它运算如加减乘除来说),并且借助位运算有时我们还能实现更简单的程序逻辑,缺点是很不直观,许多场合不能够使用. 位运算只对整数起作用,如果一个运算子不是整数,会自动转为整数后再运行.虽然在 JavaScript 内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数. 关于二进制 ==以下来

java中的位运算

刚才在imooc看php基础发现一个特别容易让我们理解的描述[关于异或运算的] 之前学习java的时候 位运算有4种,当时是这样记录的: &  按位与 (and) 两个对应二进制都为1则为1,其余全为0 |   按位或(or) 两个二进制数有一个为1则为1,只有两个0才为0 ~  按位非(NOT) 二进制中取反 ^  按位异或(XOR) 两个二进制中相同为则为0,不同则为1             其实最难以理解的就是这个异或运算. 直接搬过来(原网址点我): 我们可以从投票的角度来理解逻辑运算

C/C++中的位运算

位运算     位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果. 位运算符有:     &(按位与).|(按位或).^(按位异或).~ (按位取反). 其中,按位取反运算符是单目运算符,其余均为双目运算符.     位运算符的优先级从高到低,依次为~.&.^.|, 其中~的结合方向自右至左,且优先级高于算术运算符,其余运算符的结合方向都是自左至右,且优先级低于关系运算符.    (1)按位与运算符(&)

C#学习笔记-----C#枚举中的位运算权限分配

什么是位运算 常用的位运算主要有与(&), 或(|)和非(~), 比如: 1 01 & 00 = 00; 2 01 | 00 = 01; 3 ~01 =0 0; 运用在权限设计中 先建立一个枚举表示所有的权限管理操作: 1 [Flags] 2 public enum Permissions 3 { 4 Insert = 1, 5 Delete = 2, 6 Update = 4, 7 Query = 8 8 } [Flags]表示该枚举可以支持C#位运算. 枚举的每一项值, 我们用2的n次

C#枚举中的位运算权限分配

什么是位运算 常用的位运算主要有与(&), 或(|)和非(~), 比如: 1 01 & 00 = 00; 2 01 | 00 = 01; 3 ~01 =0 0; 运用在权限设计中 先建立一个枚举表示所有的权限管理操作: 1 [Flags] 2 public enum Permissions 3 { 4 Insert = 1, 5 Delete = 2, 6 Update = 4, 7 Query = 8 8 } [Flags]表示该枚举可以支持C#位运算. 枚举的每一项值, 我们用2的n次

嵌入式c语言中的位运算

位运算在嵌入中也是一个重要的点,下面就简单介绍和举一些有用的例子,如果有不足的话,请补充,废话不多说,直接开始! 位运算操作符有6个:&,|,^,~,>>,<< &   只有1&1才等于1,其它都为0 |   只有0|0才等于0,其它都为1 ^   异或,相异为1,相同为0,用来检查两个操作数的某对应位是否一致 ~   非,按位反,任何数的非与数本身相加都等于-1(如果不懂的话,请查看下一篇补码) >>  左移,相当乘以2-->左移之后,后