문제

나는 하루 (24 시간) 동안 독특한 숫자를 원했습니다. 다음은 제가 생각해 낸 코드입니다. 나는 그 오류/가능한 위험에 대해 궁금해했다. '나는 믿습니다'이것은 하루에 12 자리 고유 번호를 보장합니다.

논리는 현재 날짜/시간 (hhmmssmmm)을 얻고 쿼리 성능 카운터 결과의 처음 4 바이트를 동의하는 것입니다.

__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 462221] 고유 : [125907 462221]. [125907 462233] 고유 : [125907 462234] 고유 : [125907 462235] 고유 : [125907 462237] 고유 : [125907 462238] 고유 : [125907 462239] 고유 : [125907 462240] 고유 : [125907 462240] 462243] 고유 : [125907 462244] 고유 : [125907 462245] 고유 : [125907 462246] 고유 : [125907 462247] 고유 : [125907 462248] 고유 : [125907 4622249] 독특한 : [125907 46251]에 의해 사용됩니다. 고유 : [125907 462253] 고유 : [125907 462254] 고유 : [125907 462255] 고유 : [125907 462256] 고유 : [125907 462257] 고유 : [125907 462258] Millisecond, 46 Unique : [125907 62261]. 622262] 고유 : [125907 622263] 고유 : [125907 622264] 고유 : [125907 622265] 고유 : [125907 622267] 고유 : [125907 622268] 고유 : [125907 622269] 독특한 : [125907 62270]에 의해. 고유 : [125907 622273] 고유 : [12 5907 622274] 고유 : [125907 622275] 고유 : [125907 622276] 고유 : [125907 622277] 고유 : [125907 622278] 고유 : [125907 622279] 고유 : [125907 622281] 고유 : [125907 622222281] ] 고유 : [125907 622284] 고유 : [125907 622285] 고유 : [125907 622286] 고유 : [125907 622288] 고유 : [125907 622289] 고유 : [125907 62290] 고유 : [125907 6629] 고유 : [125907 6222229]. : [125907 622293] 고유 : [125907 622295] 고유 : [125907 622296] 고유 : [125907 622297] 고유 : [125907 622298] 고유 : [125907 62299] 독특 : [125907 623 62300] 125907 622302] 고유 : [125907 622304] 고유 : [125907 622305] 고유 : [125907 622306] Millsecond 변경, 62 고유 : [125907 782308] 고유 : [125907 78231] 독특한 : [125907777 782311]. : [125907 782313] 고유 : [125907 782314] 고유 : [125907 782316] 고유 : [125907 782317] 고유 : [125907 782318] 고유 : [125907 782319] 고유 한 Millisecond, 125904949949] : [1259071402 498] 고유 : [1259071402499] 고유 : [1259071402500] 고유 : [1259071402502] 고유 : [1259071402503] 고유 : [1259071402504] 고유 : [1259071402505] 고유 : [125907071402507

이제 생성 된 ID를 목록에 보관하고 새 생성 ID를 목록의 기존 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() 변화.

다른 팁

단일 코어 프로세서의 한 컴퓨터에서 실행하면 논리가 나에게 건전한 것 같습니다. 그러나 연속 통화를 위해 멀티 코어 프로세서에 대해 동일하게 유지되는지 모르겠습니다. 그러나 생성 된 숫자는 기계에서 고유하지 않을 것입니다.

호기심으로 인해 안내를 사용하지 않는 이유가 있습니까?

또는 생성 된 ID를 목록에 보관하는 것을 고려하고 있기 때문에 비교하는 이유는 무엇입니까? 스토리지가 옵션이라고 제안하기 때문에 마지막으로 사용 된 숫자를 저장하고 매번 사용하는 경우 ... 원하는 경우 매일 날짜를 저장하고 카운터를 재설정 할 수도 있습니다.

나는 상식에도 불구하고 변화하지 않은 빠른 루프에서 시간에 문제가있었습니다.

카운터 값을 여분의 몇 자리 (증분이 아닌)로 추가하고 다시 시작하거나 9999 이후에 재설정하면 모든 것을 불가능하게 만들기에 충분히 숨겨야합니다 (유명한 마지막 단어).

그런 다음 형식은 ttttttoooo입니다. 여기서 t는 시간 그림이고 O 4 자리 오프셋입니다.

AARON : 귀하의 의견에 감사드립니다. 귀하의 접근 방식을 사용하여 내가 원하는 것을 얻었습니다.

__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;
}

자정 이후 몇 초와 카운터를 사용합니다. 이렇게하면 초당 최대 100 만 명을 히트합니다. 꽤 독특해야합니다. 위의 Aaron의 코드를 사용하면 문자열을 다음과 같이 포맷합니다.

sprintf(idstr, "%05d%07d", secs_since_midnight, counter);

물론, 나는 또한 당신이 실제로 인쇄 가능한 캐릭터 (및 월/일이 아닌 연도 등)에 카운터를 크램링하고 싶을 때 Base-36 (ITOA를 통해)을 사용하는 것을 확고한 신자입니다).

귀하의 프로세스가 작은 성능 문제를 희생하고 논리를 단순하게 유지할 수 있는지 확실하지 않습니다.

두 통화 사이에서 프로세스를 1 밀리 초 동안 잠을 자면 HHMMSSMMM 형식 자체가있는 고유 번호를 보장 할 수 있습니다. 이런 식으로 연결 부분과 고유성을 두 번 확인하기 위해 유지 해야하는 목록을 제거 할 수 있습니다.

Manikanthan Velayutham // Big Think에 프로그램되었습니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top