随机数的生成
? ? ? ? ?以前用rand和srand生成過偽隨機數,偽隨機數的序列是固定的,今天學習生成真正的隨機數的生成。
利用/dev/urandom可以生成隨機數的值,/dev/urandomLinux下的熵池,所謂熵池就是當前系統下的環境噪音,描述了一個系統的混亂程度,環境噪音由這幾個方面組成,如內存的使用,文件的使用量,不同類型的進程數量等等。
#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 %d\n", randNum);}return 0; }運行結果:
mapan@mapan-virtual-machine:~/c++$ ./a.out randNum is 94961710 randNum is -523780773 randNum is 1542169420 randNum is -1632410867 randNum is 731817269 mapan@mapan-virtual-machine:~/c++$ ./a.out randNum is -1114222849 randNum is -135823700 randNum is 72499927 randNum is 1765688127 randNum is 1231660207 mapan@mapan-virtual-machine:~/c++$ ./a.out randNum is 770846624 randNum is -2058545278 randNum is 144437054 randNum is -2126469506 randNum is -1653491852 mapan@mapan-virtual-machine:~/c++$ ./a.out randNum is 133178814 randNum is 961959636 randNum is -436202053 randNum is -1998720261 randNum is -520158213 mapan@mapan-virtual-machine:~/c++$每次打印的5個隨機數都不一樣,其實它的隨機性也不太好。雪花算法生成的數的隨機性很好,通常在分布式系統中生成唯一ID。
SnowFlake算法產生的ID是一個64位的整型,結構如下(每一部分用“-”符號分隔):
? ? ? ? ? ? 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
1位標識部分,在java中由于long的最高位是符號位,正數是0,負數是1,一般生成的ID為正數,所以為0;
41位時間戳部分,這個是毫秒級的時間,一般實現上不會存儲當前的時間戳,而是時間戳的差值(當前時間-固定的開始時間),這樣可以使產生的ID從更小值開始;41位的時間戳可以使用69年,(1L << 41) / (1000L 60 60 24 365) = 69年;
10位節點部分,Twitter實現中使用前5位作為數據中心標識,后5位作為機器標識,可以部署1024個節點;
12位序列號部分,支持同一毫秒內同一個節點可以生成4096個ID;
代碼地址:https://blog.csdn.net/benpaobagzb/article/details/51638196? ? ?注釋部分是自己添加
/*?snowflake?ID?生成策略?毫秒級時間41位+機器ID?10位+毫秒內序列12位。?0?41?51?64?+-----------+------+------+?|time?|pc?|inc?|?+-----------+------+------+?前41bits是以微秒為單位的timestamp。?接著10bits是事先配置好的機器ID。?最后12bits是累加計數器。?macheine?id(10bits)標明最多只能有1024臺機器同時產生ID,sequence?number(12bits)也標明1臺機器1ms中最多產生4096個ID,?*?注意點,因為使用到位移運算,所以需要64位操作系統,不然生成的ID會有可能不正確? */??#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型 4095void 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();//獲取當前毫秒數uniqueId = nowtime << 22; //填補時間戳部分//0x3ff 1023,二進制對應11 1111 1111 //100的二進制0000 0000 0000 0000 0000 0000 0110 0100//先執行移位uniqueId |= (g_info.workid & 0x3ff) << 12; //填補節點部分if (nowtime < g_info.last_stamp){perror("error");exit(-1);}if (nowtime == g_info.last_stamp){//4095的二進制0000 1111 1111 1111 [long型]g_info.seqid = atomic_incr(g_info.seqid) & sequenceMask;if (g_info.seqid == 0) //seqid=0防止沖突,修改時間{nowtime = wait_next_ms(g_info.last_stamp);//獲取大于當前時間的time}}else{g_info.seqid = 0;}g_info.last_stamp = nowtime;uniqueId |= g_info.seqid;//填補序列號部分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; }運行結果:
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] pthread_id:4970, id [6595660141600063493] pthread_id:4970, id [6595660141600063494] pthread_id:4970, id [6595660141600063495] pthread_id:4970, id [6595660141600063496] pthread_id:4970, id [6595660141600063497] mapan@mapan-virtual-machine:~/c++$ ./a.out pthread_id:4971, id [6595660147023298560] pthread_id:4971, id [6595660147023298561] pthread_id:4971, id [6595660147023298562] pthread_id:4971, id [6595660147023298563] pthread_id:4971, id [6595660147023298564] pthread_id:4971, id [6595660147023298565] pthread_id:4971, id [6595660147023298566] pthread_id:4971, id [6595660147023298567] pthread_id:4971, id [6595660147023298568] pthread_id:4971, id [6595660147023298569] mapan@mapan-virtual-machine:~/c++$?
?
?
參考地址:https://blog.csdn.net/stpeace/article/details/45829161
總結
- 上一篇: muduo之Logger
- 下一篇: 逻辑运算符''取某值