以前用rand和srand生成過(guò)偽隨機(jī)數(shù),偽隨機(jī)數(shù)的序列是固定的,今天學(xué)習(xí)生成真正的隨機(jī)數(shù)的生成。
熵池
利用/dev/urandom可以生成隨機(jī)數(shù)的值,/dev/urandomLinux下的熵池,所謂熵池就是當(dāng)前系統(tǒng)下的環(huán)境噪音,描述了一個(gè)系統(tǒng)的混亂程度,環(huán)境噪音由這幾個(gè)方面組成,如內(nèi)存的使用,文件的使用量,不同類型的進(jìn)程數(shù)量等等。
利用/dev/urandom可以生成隨機(jī)數(shù)的值,/dev/urandomLinux下的熵池,所謂熵池就是當(dāng)前系統(tǒng)下的環(huán)境噪音,描述了一個(gè)系統(tǒng)的混亂程度,環(huán)境噪音由這幾個(gè)方面組成,如內(nèi)存的使用,文件的使用量,不同類型的進(jìn)程數(shù)量等等。
#include < stdio.h >
#include < fcntl.h >
int main()
{
int randNum = 0;
int fd = 0;
for(int i=0;i< 5;i++)
{
fd = open("/dev/urandom", O_RDONLY);
read(fd, (char *)&randNum, sizeof(int));
close(fd);
printf("randNum is %dn", randNum);
}
return 0;
}
運(yùn)行結(jié)果:
mapan@mapan-virtual-machine:~/c++$ ./a.out
randNum is 94961710
randNum is -523780773
randNum is 1542169420
randNum is -1632410867
每次打印的5個(gè)隨機(jī)數(shù)都不一樣,其實(shí)它的隨機(jī)性也不太好。雪花算法生成的數(shù)的隨機(jī)性很好,通常在分布式系統(tǒng)中生成唯一ID。
雪花算法
SnowFlake算法產(chǎn)生的ID是一個(gè)64位的整型,結(jié)構(gòu)如下(每一部分用“-”符號(hào)分隔):
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 00000000000
1位標(biāo)識(shí)部分,在java中由于long的最高位是符號(hào)位,正數(shù)是0,負(fù)數(shù)是1,一般生成的ID為正數(shù),所以為0;
41位時(shí)間戳部分,這個(gè)是毫秒級(jí)的時(shí)間,一般實(shí)現(xiàn)上不會(huì)存儲(chǔ)當(dāng)前的時(shí)間戳,而是時(shí)間戳的差值(當(dāng)前時(shí)間-固定的開(kāi)始時(shí)間),這樣可以使產(chǎn)生的ID從更小值開(kāi)始;41位的時(shí)間戳可以使用69年,(1L << 41) / (1000L 60 60 24 365) = 69年;
10位節(jié)點(diǎn)部分,Twitter實(shí)現(xiàn)中使用前5位作為數(shù)據(jù)中心標(biāo)識(shí),后5位作為機(jī)器標(biāo)識(shí),可以部署1024個(gè)節(jié)點(diǎn);
12位序列號(hào)部分,支持同一毫秒內(nèi)同一個(gè)節(jié)點(diǎn)可以生成4096個(gè)ID;
/*
snowflake
ID 生成策略
毫秒級(jí)時(shí)間41位+機(jī)器ID 10位+毫秒內(nèi)序列12位。
0 41 51 64 +-----------+------+------+ |time |pc |inc | +-----------+------+------+
前41bits是以微秒為單位的timestamp。
接著10bits是事先配置好的機(jī)器ID。
最后12bits是累加計(jì)數(shù)器。
macheine id(10bits)標(biāo)明最多只能有1024臺(tái)機(jī)器同時(shí)產(chǎn)生ID,sequence number(12bits)也標(biāo)明1臺(tái)機(jī)器1ms中最多產(chǎn)生4096個(gè)ID, *
注意點(diǎn),因?yàn)槭褂玫轿灰七\(yùn)算,所以需要64位操作系統(tǒng),不然生成的ID會(huì)有可能不正確
*/
#include < stdio.h >
#include < pthread.h >
#include < unistd.h >
#include < stdlib.h >
#include < sched.h >
#include < linux/unistd.h >
#include < sys/syscall.h >
#include < errno.h >
#include< linux/types.h >
#include< time.h >
#include < stdint.h >
#include < sys/time.h >
struct globle
{
int global_int:12;
uint64_t last_stamp;
int workid;
int seqid;
};
void set_workid(int workid);
pid_t gettid( void );
uint64_t get_curr_ms();
uint64_t wait_next_ms(uint64_t lastStamp);
int atomic_incr(int id);
uint64_t get_unique_id();
#include "snowflake.h"
struct globle g_info;
#define sequenceMask (-1L ^ (-1L < < 12L)) //L表示long型 4095
void set_workid(int workid)
{
g_info.workid = workid;
}
pid_t gettid( void )//獲取線程ID
{
return syscall( __NR_gettid );
}
uint64_t get_curr_ms() //獲取毫秒
{
struct timeval time_now;
gettimeofday(&time_now,NULL);
uint64_t ms_time =time_now.tv_sec*1000+time_now.tv_usec/1000;
return ms_time;
}
uint64_t wait_next_ms(uint64_t lastStamp)
{
uint64_t cur = 0;
do {
cur = get_curr_ms();
} while (cur <= lastStamp);
return cur;
}
int atomic_incr(int id)//累加
{
__sync_add_and_fetch(&id, 1);
return id;
}
uint64_t get_unique_id()
{
uint64_t uniqueId=0;
uint64_t nowtime = get_curr_ms();//獲取當(dāng)前毫秒數(shù)
uniqueId = nowtime < < 22; //填補(bǔ)時(shí)間戳部分
//0x3ff 1023,二進(jìn)制對(duì)應(yīng)11 1111 1111
//100的二進(jìn)制0000 0000 0000 0000 0000 0000 0110 0100
//先執(zhí)行移位
uniqueId |= (g_info.workid & 0x3ff) < < 12; //填補(bǔ)節(jié)點(diǎn)部分
if (nowtime < g_info.last_stamp)
{
perror("error");
exit(-1);
}
if (nowtime == g_info.last_stamp)
{
//4095的二進(jìn)制0000 1111 1111 1111 [long型]
g_info.seqid = atomic_incr(g_info.seqid) & sequenceMask;
if (g_info.seqid == 0) //seqid=0防止沖突,修改時(shí)間
{
nowtime = wait_next_ms(g_info.last_stamp);//獲取大于當(dāng)前時(shí)間的time
}
}
else
{
g_info.seqid = 0;
}
g_info.last_stamp = nowtime;
uniqueId |= g_info.seqid;//填補(bǔ)序列號(hào)部分
return uniqueId;
}
int main()
{
set_workid(100);
int i;
for(i=0;i< 10;i++)
{
uint64_t unquie = get_unique_id();
printf("pthread_id:%u, id [%llu]n",gettid(),unquie);
}
return;
}
運(yùn)行結(jié)果:
mapan@mapan-virtual-machine:~/c++$ ./a.out
pthread_id:4970, id [6595660141600063488]
pthread_id:4970, id [6595660141600063489]
pthread_id:4970, id [6595660141600063490]
pthread_id:4970, id [6595660141600063491]
pthread_id:4970, id [6595660141600063492]
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7157瀏覽量
89662 -
算法
+關(guān)注
關(guān)注
23文章
4631瀏覽量
93406 -
序列
+關(guān)注
關(guān)注
0文章
70瀏覽量
19600
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
如何使用MSP430內(nèi)部時(shí)鐘生成隨機(jī)數(shù)
Kintex上的真隨機(jī)數(shù)生成器測(cè)試失敗的原因有哪些?
如何去實(shí)現(xiàn)真正地單片機(jī)隨機(jī)數(shù)呢
用rand形成的不是真正的隨機(jī)數(shù),怎么才能達(dá)到真正的隨機(jī)?
神經(jīng)網(wǎng)絡(luò)的偽隨機(jī)數(shù)生成方法
偽隨機(jī)數(shù)生成算法
如何使用隨機(jī)數(shù)生成器來(lái)生成私鑰
![如何使用<b class='flag-5'>隨機(jī)數(shù)</b><b class='flag-5'>生成</b>器來(lái)<b class='flag-5'>生成</b>私鑰](https://file.elecfans.com/web1/M00/8A/2F/o4YBAFyPBWSALFKHAAQXq5BWuQ0350.png)
星系共識(shí)的隨機(jī)數(shù)生成算法對(duì)共識(shí)協(xié)議的作用
如何利用SystemVerilog仿真生成隨機(jī)數(shù)
![如何利用SystemVerilog仿真<b class='flag-5'>生成</b><b class='flag-5'>隨機(jī)數(shù)</b>](https://file.elecfans.com/web2/M00/1A/8D/poYBAGF8r2CAIWFSAABL9oKxhNI496.png)
單片機(jī)STM32F1隨機(jī)數(shù)生成探索與實(shí)踐(基于CUBEMX和KEIL5)
![單片機(jī)STM32F1<b class='flag-5'>隨機(jī)數(shù)</b><b class='flag-5'>生成</b>探索與實(shí)踐(基于CUBEMX和KEIL5)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
用于生成隨機(jī)數(shù)的電子骰子
![用于<b class='flag-5'>生成</b><b class='flag-5'>隨機(jī)數(shù)</b>的電子骰子](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Arduino Lotto隨機(jī)數(shù)生成器
![Arduino Lotto<b class='flag-5'>隨機(jī)數(shù)</b><b class='flag-5'>生成</b>器](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
隨機(jī)數(shù)生成器開(kāi)源分享
![<b class='flag-5'>隨機(jī)數(shù)</b><b class='flag-5'>生成</b>器開(kāi)源分享](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
技術(shù)分享 | 隨機(jī)數(shù)生成過(guò)慢導(dǎo)致系統(tǒng)阻塞怎么辦?
![技術(shù)分享 | <b class='flag-5'>隨機(jī)數(shù)</b><b class='flag-5'>生成</b>過(guò)慢導(dǎo)致系統(tǒng)阻塞怎么辦?](https://file.elecfans.com/web2/M00/43/4A/poYBAGJ9sjaAPEhHAAAvI_7i-HA907.jpg)
評(píng)論