39

次のコードは、毎秒乱数を出力します。

int main ()
{
    srand(time(NULL)); // Seeds number generator with execution time.

    while (true)
    {
        int rawRand = rand();

        std::cout << rawRand << std::endl;

        sleep(1);
    }
}

これらの数値が常に 0 ~ 100 の範囲になるようにサイズを小さくするにはどうすればよいでしょうか?

4

9 に答える 9

84

C++ を使用していて、適切な配布について懸念がある場合は、TR1 C++11を使用できます<random>

#include <random>

std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]

std::cout << idist(rgen) << std::endl;
于 2010-11-16T17:02:10.590 に答える
32

これまでに投稿されたすべての例は、実際にはひどく分散した結果をもたらします。コードを頻繁に実行し、統計を作成して、値がどのように歪むかを確認します。

任意の範囲[0、 N ]で実際に均一な乱数分布を生成するためのより良い方法は、次のとおりです(これは、実際には均一な分布に従うと仮定しますが、これは明らかではありません)。rand

unsigned result;
do {
    result = rand();
} while (result > N);

もちろん、その方法は遅いですが、それ良い分布を生み出します。これを行う少し賢い方法は、Nの最大の倍数を見つけて、それRAND_MAXを上限として使用することです。その後、安全に取ることができますresult % (N + 1)

ナイーブモジュラス法が悪い理由と上記が優れている理由については、Julienne使用に関する優れた記事を参照しrandください。

于 2010-11-16T15:55:01.793 に答える
27

int rawRand = rand() % 101;

(詳細については) を参照してください。

ランド - C++ リファレンス

他の人は、これが可能な限り最良の乱数の分布を与えないだろうと指摘しています. そのようなことがコードで重要な場合は、次のことを行う必要があります。

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

編集

3年後、私は編集を行っています。他の人が言ったように、rand()多くの問題があります。明らかに、今後より良い代替手段がある場合は、その使用をお勧めできません. 詳細と推奨事項については、こちらですべて読むことができます。

rand() は有害と見なされます | ゴーイングネイティブ 2013

于 2010-11-16T15:49:24.250 に答える
6

できるよ

cout << rawRand % 100 << endl; // Outputs between 0 and 99

cout << rawRand % 101 << endl; // outputs between 0 and 100

反対票を投じる人々のために。これが最初に投稿されてから1分後にコメントを残したことに注意してください。

http://www.cplusplus.com/reference/clibrary/cstdlib/randから"ただし、このモジュロ操作では、スパン内に真に均一に分散された乱数が生成されないことに注意してください (ほとんどの場合、数値が小さいほどわずかに可能性が高いため)、しかし、これは一般に、短いスパンの適切な近似値です。」

64 ビットの int で 100 個の数値を出力として使用すると、数値 0 ~ 16 は数値の 1.00000000000000000455 % で表されます (約 10 -18による 1% の同一分布に対する相対精度)、数値 17 ~ 99 は表されます数字の 0.99999999999999999913 % で。はい、完全に分散しているわけではありませんが、小さなスパンでは非常に適切な近似です。

また、OP はどこで同一分布の数値を要求するのでしょうか? 私たちが知っている限りでは、これらは小さな逸脱が問題にならない目的で使用されています (たとえば、暗号化以外のもの - そして彼らが暗号化のために数値を使用している場合、この質問は彼らが独自の暗号化を作成するにはあまりにも単純すぎます) )。

編集- 乱数の均一な分布に本当に関心がある人には、次のコードが機能します。これは、64 ビットのランダムな int の場合と同様に必ずしも最適であるとは限らないことに注意してくださいrand()

unsigned N = 100; // want numbers 0-99
unsigned long randTruncation = (RAND_MAX / N) * N; 
// include every number the N times by ensuring rawRand is between 0 and randTruncation - 1 or regenerate.
unsigned long rawRand = rand();

while (rawRand >= randTruncation) {
    rawRand = rand();  
// with 64-bit int and range of 0-99 will need to generate two random numbers
// about 1 in every (2^63)/16 ~ 10^18 times (1 million million times)

// with 32-bit int and range of 0-99 will need to generate two random numbers 
// once every 46 million times.

}
cout << rawRand % N << stdl::endl;
于 2010-11-16T15:49:28.673 に答える
4

参照してください-範囲[0、1]を取得するには、man 3 randで割ってスケーリングする必要があります。その後、ターゲット範囲に100を掛けることができます。RAND_MAX

于 2010-11-16T15:48:46.047 に答える
-1

min から max までの範囲 (両端を含む) には、次を使用します。int result = rand() % (max - min + 1) + min;

于 2010-11-16T15:49:53.290 に答える
-4

どれくらいの回答を希望しますか。

最も簡単なのは、101 で割った余りを使用して変換することです。

int value = rawRand % 101;

半純粋主義者は double を使用して再スケーリングします。

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5

純粋主義者は、rand は乱数を生成しないと言うでしょう。

参考までに、乱数の品質は、一連の数字を取得し、そのシーケンスのソースがランダムであった数学的確率を計算することによって測定されます。ランダム性を求めている場合、剰余を使用する単純なハックは非常に悪い選択です。

于 2010-11-16T15:59:59.887 に答える
-5

例として次のコードを投稿した人もいます。

int rawRand = (rand() / RAND_MAX) * 100;

rand() と RAND_MAX の両方が整数であるため、これは問題を解決する無効な方法です。C++ では、これにより整数除算が行われ、結果の小数点が切り捨てられます。RAND_MAX >= rand() であるため、その演算の結果は 1 または 0 のいずれかになります。つまり、rawRand は 0 または 100 しかありません。これを行う正しい方法は次のとおりです。

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;

オペランドの 1 つが倍精度であるため、浮動小数点除算が使用され、0 と 1 の間の適切な値が返されます。

于 2010-11-16T16:57:44.927 に答える
-5

rawRand % 101 は [0-100] を返します。

于 2010-11-16T15:48:57.620 に答える