题
我想一个数字,将保持一天(24小时)是唯一的。以下是我想出的代码;我想知道它的谬误/可能存在的风险; “我相信”,这保证了一天ATLEAST一个12位的唯一编号。
逻辑是获得当前日期/时间(hhmmssmmm)和Concat的前四个字节的查询性能计数器的结果。
__forceinline bool GetUniqueID(char caUID[MAX_STRING_LENGTH])
{
//Logic: Add HHMMSSmmm with mid 3 bytes of performance counter.
//Guarantees that in a single milli second band (0 to 999) the three bytes
//of performance counter would always be unique.
//1. Get system time, and use
bool bStatus = false;
try
{
SYSTEMTIME localtime;
GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm
LARGE_INTEGER li;
char cNT[MAX_STRING_LENGTH];//new time.
memset(cNT, '\0', sizeof(cNT));
try
{
//Try to get the performance counter,
//if one is provided by the OEM.
QueryPerformanceCounter(&li);//This function retrieves the current value of the
//high-resolution performance counter if one is provided by the OEM
//We use the first four bytes only of it.
sprintf(cNT, "%u", li.QuadPart);
}
catch(...)
{
//Not provided by OEM.
//Lets go with the GetTickCounts();
//ddHHMMSS + 4 bytes of dwTicks
sprintf(cNT,"%04d", GetTickCount());
}
//Get the first four bytes.
int iSkipTo = 0;//This is incase we'd decide to pull out next four bytes, rather than first four bytes.
int iGetChars = 4;//Number of chars to get.
char *pSub = (char*) malloc(iGetChars+1);//Clear memory
strncpy(pSub, cNT + iSkipTo, iGetChars);//Get string
pSub[iGetChars] = '\0'; //Mark end.
//Prepare unique id
sprintf(caUID, "%02d%02d%02d%3d%s",
localtime.wHour,
localtime.wMinute,
localtime.wSecond,
localtime.wMilliseconds,
pSub); //First four characters concat.
bStatus = true;
}
catch(...)
{
//Couldnt prepare. There was some problem.
bStatus = false;
}
return bStatus;
}
以下是我得到的输出:
独特之处:[125907 462224] 独特之处:[125907 462225] 独特之处:[125907 462226] 独特之处:[125907 462227] 独特之处:[125907 462228] 独特之处:[125907 462230] 独特之处:[125907 462231] 独特之处:[125907 462232] 独特之处:[125907 462233] 独特之处:[125907 462234] 独特之处:[125907 462235] 独特之处:[125907 462237] 独特之处:[125907 462238] 独特之处:[125907 462239] 独特之处:[125907 462240] 独特之处:[125907 462241] 独特之处:[125907 462243] 独特之处:[125907 462244] 独特之处:[125907 462245] 独特之处:[125907 462246] 独特之处:[125907 462247] 独特之处:[125907 462248] 独特之处:[125907 462249] 独特之处:[125907 462251] 独特之处:[125907 462252] 独特之处:[125907 462253] 独特之处:[125907 462254] 独特之处:[125907 462255] 独特之处:[125907 462256] 独特之处:[125907 462257] 独特之处:[125907 462258] 毫秒改变,46 独特之处:[125907 622261] 独特之处:[125907 622262] 独特之处:[125907 622263] 独特之处:[125907 622264] 独特之处:[125907 622265] 独特之处:[125907 622267] 独特之处:[125907 622268] 独特之处:[125907 622269] 独特之处:[125907 622270] 独特之处:[125907 622271] 独特之处:[125907 622273] 独特之处:[125907 622274] 独特之处:[125907 622275] 独特之处:[125907 622276] 独特之处:[125907 622277] 独特之处:[125907 622278] 独特之处:[125907 622279] 独特之处:[125907 622281] 独特之处:[125907 622282] 独特之处:[125907 622283] 独特之处:[125907 622284] 独特之处:[125907 622285] 独特之处:[125907 622286] 独特之处:[125907 622288] 独特之处:[125907 622289] 独特之处:[125907 622290] 独特之处:[125907 622291] 独特之处:[125907 622292] 独特之处:[125907 622293] 独特之处:[125907 622295] 独特之处:[125907 622296] 独特之处:[125907 622297] 独特之处:[125907 622298] 独特之处:[125907 622299] 独特之处:[125907 622300] 独特之处:[125907 622301] 独特之处:[125907 622302] 独特之处:[125907 622304] 独特之处:[125907 622305] 独特之处:[125907 622306] 毫秒改变,62 独特之处:[125907 782308] 独特之处:[125907 782310] 独特之处:[125907 782311] 独特之处:[125907 782312] 独特之处:[125907 782313] 独特之处:[125907 782314] 独特之处:[125907 782316] 独特之处:[125907 782317] 独特之处:[125907 782318] 独特之处:[125907 782319] 毫秒改变,125 独特之处:[1259071402495] 独特之处:[1259071402497] 独特之处:[1259071402498] 独特之处:[1259071402499] 独特之处:[1259071402500] 独特之处:[1259071402502] 独特之处:[1259071402503] 独特之处:[1259071402504] 独特之处:[1259071402505] 独特:1259071402507]
现在我想保持生成的ID在列表中,并且比较新生成一个与列表中现有的。如果已经在列表中存在,那么好,我可以肯定跳过数并生成另一个,但可以肯定,并明确这个逻辑会失败。
非常感谢您的意见/建议/更新/等。
由于 JT。
解决方案
我的解决办法是让系统时间和一个计数器添加到(伪码):
static int counter = 0;
static Time lastTime;
String getNextId() {
Time now = System.getTime();
if (lastTime == now)
counter ++;
else
counter = 0;
return now+counter;
}
这将保证我会得到一个新的ID,甚至当我调用的方法往往比getTime()
变化。
其他提示
在逻辑听起来似乎对我来说,如果你从一台机器上的单核处理器运行它。我不知道是否同样适用于连续调用多核处理器,但是。所生成的数字肯定不会跨机器唯一的,但
出于好奇,有没有你不使用GUID的理由吗?
或者因为你正在考虑保持生成的ID列表中进行比较,你为什么不能建立一个发电机?既然你认为存储是一个选项,如果您存储最近使用的数量,并增加它的每一个使用...你可以每天甚至存储日期和重置计数器,如果你想。
我曾与在快环时代的问题,他们没有尽管它是常理,他们应该改变(你必须在操作系统无法控制,所以你不能假设的时间变化,每x毫秒等等。)
添加计数器值作为一个额外的几个数字(而不是增量)和重置它重新启动或9999之后应该隐藏这足以令它几乎不可能发生(鬼才)。
格式是然后TTTTTToooo其中T是你的时间图和邻4位数的偏移。
阿龙:感谢您的意见,我用你的方法来得到我想要的东西。
__forceinline bool GetUniqueIDEx(char caUID[MAX_STRING_LENGTH])
{
//Logic: Add HHMMSSmmm with 3 bytes counter.
//Guarantees a unique number for a calendar date,
//that in a single milli second band (0 to 999) the three bytes
//of counter would always be unique.
//1. Get system time, and use
bool bStatus = false;
try
{
GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm
char cNT[MAX_STRING_LENGTH];//new time.
memset(cNT, '\0', sizeof(cNT));
if(m_nCounter> MAX_COUNTER_LIMIT)
{
m_nCounter= 0;
}
sprintf(cNT, "%03d", ++m_nCounter);
//Prepare unique id
sprintf(caUID, "%02d%02d%02d%03d%s",
localtime.wHour,
localtime.wMinute,
localtime.wSecond,
localtime.wMilliseconds,
cNT);
bStatus = true;
}
catch(...)
{
//Couldnt prepare. There was some problem.
bStatus = false;
}
return bStatus;
}
我会用秒自午夜,然后计数器。这使您最多每秒一次千万的点击。应该是相当独特的。使用上面亚伦的代码,格式化字符串为:
sprintf(idstr, "%05d%07d", secs_since_midnight, counter);
当然,我也使用基36(通过itoa)当你真的想将所有计数器进几可打印字符的坚定信仰者(和年份,而不是月/日,等一天。)
我不知道你的程序是否可以牺牲微小的性能问题,并保持逻辑简单。
我们可以保证与HHMMSSmmm格式本身唯一的号码,如果你把你的进程时间为1毫秒的两个电话之间睡觉。通过这种方式,您可以消除串联组成部分,也是该列表中,您必须保持仔细检查独特性。
Manikanthan Velayutham //编程以认为BIG