3

宝くじスケジューラーを設計したいのですが、LCG に似た非常に優れた (疑似) 乱数ジェネレーターが必要ですが、他にもっと良い選択肢があるかどうか疑問に思っていました。私は特にCで書かれた乱数発生器を探しています.

LCGコード:

unsigned long lcg_rand(unsigned long a)
{
  return (a * 279470273UL) % 4294967291UL;
}

srand()また、この目的に使用できるかどうか、または精度が高くないかどうかを知りたいですか?

4

3 に答える 3

2

メルセンヌ ツイスターも選択肢の 1 つです。別のオプションはキャリー付きの減算です

于 2013-09-29T22:09:50.600 に答える
1

C 関数のほとんどの実装では、 LGCrand()のバリエーションを使用します。 、コンピューター化されたランダムジェネレーターが真のランダムではないように、それは疑似ランダムにすぎません。を使用するとランダム性が向上しますが、完全にはなりません。それは、使用されるシードがどれほど多様でランダムであるかによって異なります。たとえば、 で同じ同一のシードを使用して n 回呼び出した場合、結果は同じになります。しかし、毎回呼び出す場合(および呼び出し間の経過時間が のティックの期間よりも長い場合) は、ランダム ジェネレーターが改善されます。rand()srand()srand()rand()srand()srand(clock())clock()

以下は単純なコード例で、両方clock()とサポート関数NotRecentlyUsed() ( minmaxの小さなサンプル用) が使用されています。

#include <ansi_c.h>

#define _UNIQUE_

int randomGenerator(int min, int max);
int NotUsedRecently (int number);

int main(void)
{
    int i=0;
    for(i=0;i<1000;i++)
    {
        printf("%d,\t", randomGenerator(0, 20));
            if(i%20 == 0) printf("\n");
    }
    getchar();
    return 0;   
}

//////////////////////////////////////////////////////
//generates pseudo random numbers between min and max
//If it is desired to use this without a guarantee of uniqueness
//for a specified span of values, un-define _UNIQUE_
//
int randomGenerator(int min, int max)
{
    int random, trying;

    trying = 1;         
    while(trying)
    {
        srand(clock());
        random = (rand()/32767.0)*(max+1);
        ((random >= min)
#ifdef _UNIQUE_
            && NotUsedRecently(random) 
#endif
            ) ? (trying = 0) : (trying = 1);
    }

    return random;
}

//This function is used to guarantee that a span of n generated values
//will not be the same. To adjust the span, change the index in 
//static int recent[n];  Note: it is required that n < (max-min)
//otherwise an infinite loop will occur
int NotUsedRecently (int number)
{
    static int recent[20];//Use No greater value for index than max - min
    int i,j;
    int notUsed = 1;

    for(i=0;i<(sizeof(recent)/sizeof(recent[0]));i++)  (number != recent[i]) ? (notUsed==notUsed) : (notUsed=0, i=(sizeof(recent)/sizeof(recent[0])));
    if(notUsed) 
    {
        for(j=(sizeof(recent)/sizeof(recent[0]));j>1;j--)
        {
            recent[j-1] = recent[j-2];
        }
        recent[j-1] = number;
    }
    return notUsed;
}
于 2013-09-29T22:39:51.170 に答える