web-dev-qa-db-ja.com

範囲内の乱数を生成しますか?

可能性のある複製:
Objective-Cでの乱数の生成

範囲内の乱数を生成するにはどうすればよいですか?

16
TheLearner

これを実際に正しく理解するのは、ほとんどの人が理解するよりも少し難しいです。

int Rand_lim(int limit) {
/* return a random number between 0 and limit inclusive.
 */

    int divisor = Rand_MAX/(limit+1);
    int retval;

    do { 
        retval = Rand() / divisor;
    } while (retval > limit);

    return retval;
}

%(または/)のみを使用して範囲内の数値を取得しようとすると、必然的にスキューが発生します(つまり、一部の数値は他の数値よりも頻繁に生成されます)。

%を使用すると結果が歪む理由について:必要な範囲がRand_MAXの約数でない限り、スキューは避けられません。小さな数字から始める場合、その理由は簡単にわかります。キャンディーを10個(切り取ったり、壊したりすることはできないと想定)、3人の子供に均等に分配することを検討してください。明らかにそれはできません。すべてのキャンディーを配った場合、最も近いのは2人の子供が3つのキャンディーを手に入れ、そのうちの1人が4つを手に入れることです。

すべての子供が同じ数のキャンディーを手に入れる方法は1つしかありません。最後のキャンディーをまったく配らないようにしてください。

これを上記のコードに関連付けるために、キャンディーを1から10、子供を1から3に番号付けしてみましょう。最初の除算では、子供が3人いるため、除数は3です。次に、バケツからランダムなキャンディーを取り出し、その数を調べて3で割り、その子供に渡します。ただし、結果が3より大きい場合(つまり、キャンディーの数10を選択した場合)は、それを手渡す-私たちはそれを捨て、別のキャンディーを選びます。

もちろん、C++の最新の実装(つまり、C++ 11以降をサポートする実装)を使用している場合は、通常、標準ライブラリのdistributionクラスを使用する必要があります。上記のコードはstd::uniform_int_distributionと最も密接に対応していますが、標準ライブラリにはuniform_real_distributionだけでなく、いくつかの不均一分布のクラスも含まれています(ベルヌーイ、ポアソン、通常、おそらく私が使用しない他のカップル) t現時点では覚えています)。

70
Jerry Coffin
int Rand_range(int min_n, int max_n)
{
    return Rand() % (max_n - min_n + 1) + min_n;
}

分数の場合:

double Rand_range(double min_n, double max_n)
{
    return (double)Rand()/Rand_MAX * (max_n - min_n) + min_n;
}
7
Michał Trybus

[min、max)の範囲の整数値の場合:

double scale = (double) (max - min) / Rand_MAX;
int val = min + floor(Rand() * scale) 
1
John Bode