質問

私は一日(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 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;
}

これは、私はより頻繁にgetTime()の変化よりもメソッドを呼び出した場合でも、新しいIDを取得したいことを保証します。

他のヒント

ロジックを使用すると、シングルコアプロセッサ上でのマシンからそれを実行している場合、私に聞こえるようです。同じことが、連続通話のためのマルチコアプロセッサのために保持している場合、私は、しかし、知りません。生成された数字は間違いなくしかし、マシン全体で一意ではありません。

好奇心から、あなたはGUIDを使用していない理由はありますか?

それとも、比較するのリストで生成されたIDを保っ検討されているので、なぜあなたはジェネレータを作成することはできませんか?あなたはストレージがオプションであることを示唆しているので、あなたが最後に使用された番号を保存し、それをすべての使用をインクリメントした場合、あなたが望むならば、...あなたも毎日の日付を格納し、カウンタをリセットすることができます。

私はそれが常識であるにもかかわらず、彼らは変更されていない高速のループ内での時間に問題があった、彼らは(あなたは時間がすべてのXミリ秒などを変更することを想定することはできませんので、あなたはOSを制御することはできません。)必要があります

余分な数の数字(ない増分など)としてカウンタ値を追加し、再起動時にまたは9999の後にそれをリセットして、すべてが、(有名な最後の言葉を)起こることは不可能で作ることが、これは十分に隠す必要があります。

の形式は、次にTはあなたの時間図とあなたの4桁はオフセットOでTTTTTTooooである。

アーロン:あなたのコメントのおかげで、私は私が欲しかったものを手に入れるためにあなたのアプローチを使用していました。

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

私は真夜中、その後、カウンターからの秒数を使用します。これは、秒あたり10万枚のヒットにあなたをあきらめます。かなりユニークでなければなりません。上記のアーロンのコードを使用して、文字列をフォーマットとしてます:

sprintf(idstr, "%05d%07d", secs_since_midnight, counter);
あなたは本当にいくつかの印刷可能な文字にカウンターを詰め込むしたいとき

もちろん、私は(と年の日ではなく、月/日など、。)また、ベース36(itoaは経由)を使用して固く信じています

私はあなたのプロセスは小さなパフォーマンスの問題を犠牲にして、ロジックをシンプルに保つことができるかどうかはわからない。

次の2回の呼び出しの間で1ミリ秒のためにスリープ状態にあなたのプロセスを置く場合は、

私たちはHHMMSSmmm形式自体に固有の番号を保証することができます。この方法によって、あなたが一意性を再確認するために維持する必要が連結部と、リストを排除することができます。

Manikanthan Velayutham // BIGを考えるようにプログラム

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top