我想一个数字,将保持一天(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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top