2

だから、私はこれに夢中になっています。

rand() % 6 は、常に 0 ~ 5 の結果を生成します。

ただし、その間が必要な場合は、6-12 としましょう。

rand() % 6 + 6 が必要ですか

0+6 = 6.
1+6 = 7.
...
5+6 = 11. ???

では、間隔を 6 ~ 12 にしたい場合、+ 7 する必要がありますか? しかし、0+7 = 7 です。6をランダム化するのはいつですか?

ここで何が欠けていますか?乱数を 6 から 12 の間で取得する正しい方法はどれですか? なぜ?ここで何かが足りないようです。

4

4 に答える 4

12

C++11がオプションの場合、ランダム ヘッダーと uniform_int_distribution を使用する必要ありますJames がrandを使用してコメントで指摘したように%、偏った分布を含む多くの問題があります。

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;

    std::mt19937 e2(rd());

    std::uniform_int_distribution<int> dist(6, 12);

    for (int n = 0; n < 10; ++n) {
            std::cout << dist(e2) << ", " ;
    }
    std::cout << std::endl ;
}

randを使用する必要がある場合は、次のようにします。

rand() % 7 + 6

アップデート

使用するより良い方法randは次のとおりです。

6 + rand() / (RAND_MAX / (12 - 6 + 1) + 1)

これはC FAQから取得しましたが、特定の範囲でランダムな整数を取得するにはどうすればよいですか?と説明されています。質問。

更新 2

ブーストもオプションです。

#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

int main()
{
  boost::random::mt19937 gen;
  boost::random::uniform_int_distribution<> dist(6, 12);

  for (int n = 0; n < 10; ++n) {
    std::cout << dist(gen) << ", ";
  }
  std::cout << std::endl ;
}
于 2013-10-23T22:15:45.597 に答える
5

rand() % 7 + 6 が必要です。

rand() %7 からの最小数: 0. rand() %7 からの最大数: 6.

0 + 6 = 6. 6 + 6 = 12.

于 2013-10-23T22:14:35.947 に答える
4

モジュラス演算a % bは、除算の剰余を計算しa / bます。明らかに除算の剰余はより小さくなければならずbaがランダムな正の整数a%bである場合、 は範囲 0 .. (b-1) のランダムな整数です。


あなたが言及したコメントで:

rand()%(最大-最小)+最小

このアルゴリズムは、ハーフオープン範囲 [min, max) の値を生成します。(つまり、max は範囲外であり、単に境界を示します。整数の範囲について話しているので、この範囲は閉じた範囲 [min, max-1] と同等です。)

「0 - 5」または「6 - 12」と書くと、それらは閉じた範囲です。上記の式を使用するには、同等の半開範囲を示す値を使用する必要があります: [0, 6) または [6, 13)。

rand() % (6-0) + 0

rand() % (13-6) + 6

rand() % (max-min) + minこれは、明らかにすでに学習したルールの単なる一般化であることに注意してください。これrand() % nは、範囲 0 ~ (n-1) の値を生成します。同等の半開範囲は [0, n) とrand() % n==rand() % (n-0) + 0です。

したがって、レッスンは次のとおりです。半開きの範囲と閉じた範囲を混同しないでください。


2 つ目の教訓は、これは、独自の分布を手動で計算<random>するよりも使いやすい別の方法を示しているということです。rand()ビルトインをuniform_int_distribution使用すると、目的の包括的な範囲を直接指定できます。0 から 5 の範囲が必要な場合はuniform_int_distibution<>(0, 5)、6 から 12 の範囲が必要な場合はuniform_int_distribution<>(6, 12).

#include <random>
#include <iostream>

int main() {
  std::default_random_engine eng;
  std::uniform_int_distribution<> dist(6, 12);

  for (int i=0; i<10; ++i)
    std::cout << dist(eng) << " ";
}

rand()%7+6はより簡潔ですが、使いやすいというわけではありません。

于 2013-10-24T16:44:24.430 に答える
1

ここにはいくつかの概念があります。

まず、範囲があります:[包括的であることを示します。)排他的であることを示します。

モジュラス演算子 % n は[0,n)- 0,..n-1を生成します

その結果に値を追加すると、範囲の両端に同じ値が追加されます。

%n + 6 = [n,n+6)

ここで、n が 6 の場合、あなたの場合のように、出力は次のようになります。[0,6)

%6 + 6 = [6,12)

今、あなたが欲しいのは[6,13)

そこから 6 を引きます。

[0,7) + 6 => n%7 + 6

第 2 に、rand() の使用の問題があります。データがランダムであるかどうかを本当に気にするかどうかによって異なります。ランダムであることを本当に気にするなら、今年のGoing Native 2013 での rand() 使用の落とし穴に関する Stefan T Lavalej の講演を見ることを強くお勧めします。彼はまた、あなたが何を使うべきかについても説明します。

rand() のランダム性が問題にならない場合は、ぜひ使用してください。

于 2013-10-23T23:03:21.853 に答える