0

1 日 (24 時間) 固有のままになる番号が必要でした。以下は私が思いついたコードです。その誤謬/考えられるリスクについて疑問に思っていました。これにより、少なくとも 1 日は 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] ユニーク7:[12623] [125907 462233] ユニーク:[125907 462234] ユニーク:[125907 462235] ユニーク:[125907 462237] ユニーク:[125907 462238] ユニーク:[125907 462239] ユニーク:[125907 462240] ユニーク:[125907 90215] 462243] ユニーク:[125907 462244] ユニーク:[125907 462245] ユニーク:[125907 462246] ユニーク:[125907 462247] ユニーク:[125907 462248] ユニーク:[125907 462249] ユニーク:[125907 462255]ユニーク:[125907 462253] ユニーク:[125907 462254] ユニーク:[125907 462255] ユニーク:[125907 462256] ユニーク:[125907 462257] ユニーク:[125907 462258] ミリ秒変更、46 ユニーク:[125907 622215]9 622262] ユニーク:[125907 622263] ユニーク:[125907 622264] ユニーク:[125907 622265] ユニーク:[125907 622267] 固有:[125907 622268] 固有:[125907 622269] 固有:[125907 622270] 固有:[125907 622271] 固有:[125907 622273] 固有:[125907 622274] 固有:[125907 622274] 固有:[125907] 6ユニーク:[125907 622276] ユニーク:[125907 622278] ユニーク:[125907 622279] ユニーク:[125907 622281] ユニーク:[125907 622282] ユニーク:[125907 622283] ユニーク:[125907 622284]ユニーク:[125907 622286] ユニーク:[125907 622288] ユニーク:[125907 622289] ユニーク:[125907 622290] ユニーク:[125907 622291] ユニーク:[125907 622292] ユニーク:[125907 622293] ユニーク7:[122595] [125907 622296] ユニーク:[125907 622297] ユニーク:[125907 622298] ユニーク:[125907 622299] ユニーク:[125907 622300] ユニーク:[125907 622301] ユニーク:[125907 622302] ユニーク:[125907 622307] 622305] 固有:[125907 622306] ミリ秒変更、62 固有:[125907 782308] 固有:[125907 782310] ユニーク:[125907 782311] ユニーク:[125907 782312] ユニーク:[125907 782313] ユニーク:[125907 782314] ユニーク:[125907 782316] ユニーク:[125907 782317] ユニーク:[125907 782317] 782319] Millisecond changed, 125 Unique:[1259071402495] Unique:[1259071402497] Unique:[1259071402498] Unique:[1259071402499] Unique:[1259071402500] Unique:[1259071402502] Unique:[1259071402503] Unique:[1259071402504] Unique:[1259071402505 ] ユニーク:[1259071402507][1259071402504] ユニーク:[1259071402505] ユニーク:[1259071402507][1259071402504] ユニーク:[1259071402505] ユニーク:[1259071402507]

現在、生成された ID をリストに保持し、新しく生成された ID をリスト内の既存のものと比較することを考えています。リストに既に存在する場合は、確かに番号をスキップして別の番号を生成できますが、確かにそして明らかにこのロジックは失敗します。

コメント/提案/更新/などをいただければ幸いです。

ありがとうJT。

4

6 に答える 6

1

シングルコア プロセッサ上の 1 台のマシンから実行している場合、ロジックは私には聞こえます。ただし、連続呼び出し用のマルチコア プロセッサにも同じことが当てはまるかどうかはわかりません。ただし、生成された数値はマシン間で一意であるとは限りません。

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

または、生成された ID をリストに保持して比較することを検討しているのに、なぜジェネレーターを作成できないのでしょうか? ストレージがオプションであることを示唆しているため、最後に使用した番号を保存し、使用するたびにインクリメントすると...必要に応じて、日付を保存してカウンターを毎日リセットすることもできます。

于 2009-03-25T08:39:47.080 に答える
1

私の解決策は、システム時間を取得し、それにカウンターを追加することでした(疑似コード):

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()ます。

于 2009-03-25T08:43:12.283 に答える
0

真夜中からの秒数を使用してから、カウンターを使用します。これにより、1秒あたり最大1,000万ヒットが得られます。かなりユニークなはずです。上記のAaronのコードを使用して、文字列を次のようにフォーマットします。

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

もちろん、カウンターをいくつかの印刷可能な文字(および月/日ではなく日など)に詰め込みたい場合は、base-36(itoa経由)を使用することも固く信じています。

于 2009-04-27T02:27:16.690 に答える
0

アーロン:コメントありがとうございます。あなたのアプローチを使って、欲しいものを手に入れました。

__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;
}
于 2009-04-03T05:34:10.040 に答える
0

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

2 つの呼び出しの間にプロセスを 1 ミリ秒間スリープ状態にすると、HHMMSSmmm 形式自体で一意の番号を保証できます。このようにして、連結部分と、一意性を再確認するために維持する必要があるリストを排除できます。

Manikanthan Velayutham // 大きく考えるようにプログラムされている

于 2009-11-11T18:17:51.940 に答える
0

私は高速ループの時間に問題がありましたが、常識であるにもかかわらず変更されていません (OS を制御できないため、時間が x ミリ秒ごとに変化するとは想定できません)。

カウンター値を(インクリメントではなく)余分な数桁として追加し、再起動時または9999の後にリセットすると、これを十分に隠して、ほとんど不可能にする必要があります(有名な最後の言葉)。

フォーマットは TTTTTToooo です。ここで、T は時間の数字で、o は 4 桁のオフセットです。

于 2009-03-25T12:55:33.627 に答える