n位二進(jìn)制表示的最大值
雪花算法已經(jīng)初步完成了『ㄔ澹現(xiàn)在我們再來看幾個(gè)位操作曹洽。先看第一個(gè),還是左移操作辽剧,不過這里演示負(fù)數(shù)左移:
<<
看這個(gè)之前送淆,我們先看一個(gè)關(guān)鍵的數(shù)字,最大的負(fù)整數(shù)抖仅,-1L轉(zhuǎn)換為二進(jìn)制后的形式:
這里注意二進(jìn)制數(shù)字的思路是相反的坊夫,在負(fù)整數(shù)中,除去負(fù)號外撤卢,那個(gè)數(shù)字越大环凿,這個(gè)負(fù)數(shù)就越小,在Java的二進(jìn)制形式中放吩,首位代表正負(fù)號智听,除去首位,剩下的數(shù)字值越大渡紫,真的就代表數(shù)字本身越大到推,無論正負(fù)。從上面打印可以看出惕澎,-1L的二進(jìn)制形式就是一個(gè)最大負(fù)整數(shù)莉测。
我們前面討論位運(yùn)算提到過左移運(yùn)算 << ,那么負(fù)數(shù)左移會出現(xiàn)什么情況的呢唧喉?下面來看一個(gè)例子:
從字面值上來看捣卤,負(fù)整數(shù)左移和正整數(shù)左移效果是一樣的忍抽,就是把字面值變小了,二進(jìn)制的形式也能看出董朝,所有的1左移后鸠项,右面直接補(bǔ)0,效果也是把數(shù)字變小了子姜。
前面我們說過兩個(gè)位移操作祟绊,那兩個(gè)我們主要是關(guān)注二進(jìn)制形式的數(shù)字效果,這里我們就要看字面值的變化了哥捕。-1L向左位移1位牧抽,字面值就變成
-1L * 2^1
如果向左位移n位,字面值就會變成:
-1L * 2^n
這就是-1L向左位移的字面值變化規(guī)律遥赚。
看完負(fù)數(shù)左移操作阎姥,再來看一個(gè)位移操作,取反操作:
~
取反的意思也是針對二進(jìn)制形式的數(shù)字說的鸽捻,因?yàn)樗形簧系臄?shù)字不是0就是1,所以取反的操作就是把0變成1泽腮,把1變成0御蒲,來看幾個(gè)例子:
上面的正整數(shù)3L,取反后诊赊,字面值變成了-4L厚满,二進(jìn)制的數(shù)字中的0和1也徹底反了,0變成1,1變成0碧磅。而負(fù)整數(shù)-9L字面值變成了8L碘箍,二進(jìn)制數(shù)字的變化也是一樣的規(guī)律。大家可以多試幾次鲸郊,從上面的內(nèi)容可以總結(jié)出取反的規(guī)律:
1丰榴、取反后,正整數(shù)變成了負(fù)整數(shù)秆撮,負(fù)整數(shù)變成了正整數(shù)
2四濒、取反后,無論原來是正數(shù)還是負(fù)數(shù)职辨,結(jié)果都會變成? ?(n+1) * -1L
取反操作我們也不看二進(jìn)制數(shù)字的變化盗蟆,但看字面值的變化,可以總結(jié)出上面的規(guī)律舒裤。
現(xiàn)在有個(gè)需求喳资,如果有三位二進(jìn)制數(shù),那么能表示的最大正數(shù)就是? 111腾供,也就是7仆邓,如果有四位就是1111鲜滩,也就是15,如果有n位如何用位運(yùn)算表示宏赘?其實(shí)公式很容易推出來绒北,就是?
2^n-1
這個(gè)公式和上面的負(fù)數(shù)左移很相似,我們來使用-1L進(jìn)行左移:
-1L << n
這樣n如果是3和4就分別對應(yīng)-8L和-16L察署,從字面值上看和我們的需求很接近闷游,我們再來進(jìn)行取反操作:
~(-1L << n)
這樣3和4分別對應(yīng)的就是7和15了!上面這個(gè)位運(yùn)算公式贴汪,就是求出n位二進(jìn)制數(shù)能表示的最大整數(shù)的公式脐往!
再來看雪花算法中的限制,數(shù)據(jù)中心id和機(jī)器id分別占5位扳埂,最大數(shù)都是31业簿,毫秒內(nèi)序列占12位,最大值是4095阳懂,這個(gè)值直接定義上是最快的梅尤,現(xiàn)在也可以用高效的位運(yùn)算計(jì)算出來了:
不超過最大值的序列遞增
雪花算法的毫秒內(nèi)序列有兩個(gè)操作,一個(gè)是在同一毫秒內(nèi)加一岩调,另一個(gè)是如果超過最大值巷燥,就強(qiáng)制等到下一個(gè)不同的時(shí)間從新開始序列。這里也是可以用位操作實(shí)現(xiàn)的号枕。這里首先討論下面的位操作:
&
這個(gè)操作的意思是同一個(gè)位上缰揪,都是1,結(jié)果才是1葱淳,否則就是0.下面用二進(jìn)制數(shù)字演示一下:
15L 轉(zhuǎn)換為2進(jìn)制形式后有個(gè)特點(diǎn)钝腺,就是前面所有位上都是1,那么這個(gè)時(shí)候赞厕,其實(shí)較小的數(shù)是多少結(jié)果就是多少艳狐。從而可以推理出,只要較大的數(shù)有這個(gè)特點(diǎn)皿桑,那么&操作的結(jié)果都和較小的數(shù)的值一樣僵驰。如果超過最大值會怎么樣呢?
可以看到唁毒,只要超過1蒜茴,那么結(jié)果就會歸0,再加上1浆西, 15L & 17L的話粉私,結(jié)果又會是1。這樣的&操作可以防止數(shù)字超過某個(gè)最大限制近零。這種特性正好用在毫秒內(nèi)序列的加一操作上诺核。
seq = (seq + 1) & 4095抄肖;
像上面那種寫法,其實(shí)最終值和
seq = seq + 1
效果是一樣的窖杀,不同的是漓摩,一旦超過了4095,seq會從新變成0入客。