2016-10-01 18 views
3

Aとbの間に乱数を入れる方法があるのだろうと思っていました。数字が特定の条件を満たしていれば、AとBの間の他のすべての数よりも出現する可能性が高く、例:A = 1、B = 10の場合は、数字が小さいほど数字が表示される可能性が高くなります。その場合は1が最も可能性が高く、10が最も低い場合があります。尤度の異なるランダムなint

すべてのヘルプは高く評価され:)あなたは、値の配列を作ることができ

+0

zipf配信をお探しですか? http://stackoverflow.com/questions/9983239/how-to-generate-zipf-distributed-numbers-efficienty – HazemGomaa

答えて

2

C++ 11 <random>ヘッダーをC++標準に追加しました としょうかん。このヘッダーは、C++にはるかに高い品質の乱数ジェネレータを提供します。 srand()rand()を使用することは、品質の保証はないので、決して非常に良いアイデアはありませんでしたが、今は本当に使えません。

あなたの例では、おそらく「離散三角分布」と呼ばれるように思えます。確率質量関数は三角形のように見えます。

1 generated 233 times. 
2 generated 425 times. 
3 generated 677 times. 
4 generated 854 times. 
5 generated 1130 times. 
6 generated 1334 times. 
7 generated 1565 times. 
8 generated 1804 times. 
9 generated 1978 times. 

物事もっと複雑な:私のために次の出力を与える

auto discrete_triangular_distribution(int max) { 
    std::vector<int> weights(max); 
    std::iota(weights.begin(), weights.end(), 0); 
    std::discrete_distribution<> dist(weights.begin(), weights.end()); 
    return dist; 
} 

int main() { 
    std::random_device rd; 
    std::mt19937 gen(rd()); 
    auto&& dist = discrete_triangular_distribution(10); 
    std::map<int, int> counts; 
    for (int i = 0; i < 10000; i++) 
     ++counts[dist(gen)]; 
    for (auto count: counts) 
     std::cout << count.first << " generated "; 
     std::cout << count.second << " times.\n"; 
} 

:C++でこれを実装するための最も簡単な(しかし、おそらく最も効率的ではない)方法は、離散分布が<random>に含まれることになりますこれよりも既存のディストリビューションのいずれかを使用する方が良いでしょう(私はすべての一般的な統計的ディストリビューションが含まれていると言われています)、独自のディストリビューションを作成することで、あまり難しくありません。関数呼び出し演算子はランダムビットジェネレータをとり、これらのビットを使って(inこの場合)乱数。しかし、おそらくテスト目的のためにランダムな文字列や任意のランダムなオブジェクトを作成することができます。

+0

質問から、アウトプットは* [1、10] *の範囲になければならないと思われます。 –

+0

これは単なる例です。 –

+0

ありがとうございました!私はちょうど変更しました:++ counts [dist(gen)]; 〜++カウント[abs(10 - dist(gen))];より低い数字をもっと可能にする:) – AdminBenni

-1

(悪い英語/文法/質問には申し訳ありません)、より多くの可能性の高い値は、複数のインデックスを持ち、その後、ランダムなインデックスを選択してください。

例:

int max= rand() % 10 + 1; // This is your max value 
int random = rand() % max + 1; // This is you result 

どちらの方法1を行います:

int random[55]; 
int result; 

    int index = 0; 
    for (int i = 1 ; i <= 10 ; ++i) 
     for (int j = i ; j <= 10 ; ++j) 
      random[index++] = i; 

result = random[rand() % 55]; 

また、あなたはあなたがあなたの乱数を選択し、次に最大数を選択し初めて、二回乱数を取得しようとすることができます2よりも可能性が高く、3よりも可能性が高い... 9よりも10よりも高い可能性があります。

+1

はい、そうです。誰もが正しい解決策を求めています。 –

2

あなたの質問では、どの配布を使用するか指定していません。 1つのオプション(多くのうちの1つ)は(negative) exponential distributionを使用することです。この分布は、パラメータλによってパラメータ化される。の各値に対して、、最大結果は(ウィキペディアから、Skbkekas、3.0 BY CCにより)

enter image description here

(のみ指定された範囲内の結果を戻すために処理される必要がある)非有界である

そう任意&amp;は理論的には動作します。しかし、(ウィキペディアから、Skbkekas、3 BY CCことで

enter image description here

CDFの性質。0)

1 /(to - from + 1)の順で何かを選ぶことを意味する。

次のクラスは標準的なライブラリ配布のように機能します。内部的には、結果は[from、to]になるまでループ内で数値を生成します。ここで

#include <iostream> 
#include <iomanip> 
#include <string> 
#include <map> 
#include <random> 

class bounded_discrete_exponential_dist { 
public: 
    explicit bounded_discrete_exponential_dist(std::size_t from, std::size_t to) : 
     m_from{from}, m_to{to}, m_d{0.5/(to - from + 1)} {} 
    explicit bounded_discrete_exponential_dist(std::size_t from, std::size_t to, double factor) : 
     m_from{from}, m_to{to}, m_d{factor} {} 

    template<class Gen> 
    std::size_t operator()(Gen &gen) { 
     while(true) { 
      const auto r = m_from + static_cast<std::size_t>(m_d(gen)); 
      if(r <= m_to) 
       return r; 
     } 
    } 

private: 
    std::size_t m_from, m_to; 
    std::exponential_distribution<> m_d; 
}; 

それを使用しての例です:

int main() 
{ 
    std::random_device rd; 
    std::mt19937 gen(rd()); 

    bounded_discrete_exponential_dist d{1, 10}; 

    std::vector<std::size_t> hist(10, 0); 
    for(std::size_t i = 0; i < 99999; ++i) 
     ++hist[d(gen) - 1]; 

    for(auto h: hist) 
     std::cout << std::string(static_cast<std::size_t>(80 * h/99999.), '+') << std::endl; 
} 

実行が、それはこのようなヒストグラムを出力する場合:あなたの基本的な乱数生成器は、高品質を生成する必要があり

$ ./a.out 
++++++++++ 
+++++++++ 
+++++++++ 
++++++++ 
+++++++ 
+++++++ 
+++++++ 
+++++++ 
++++++ 
++++++ 
+0

本当に素敵な答えですが、私は@Milesの答えが自分のニーズに少し良く合っていると思っていました。 – AdminBenni

+1

@AdminBenniいいですね。ではごきげんよう。 –

0

を、0から1までの一様乱数 - イプシロン。次に、それを変換してあなたが望む分布を得る。最も単純な変換はもちろん、0からN-1までの整数を必要とする一般的なケースでは(int)(p * N)です。

しかし、あなたが試すことができる他の多くの変換があります。たとえば、平方根を1.0に、バイアスを1 - pにしてバイアスをゼロに設定します。あるいは、ポアソン分布を調べることができます。ポアソン分布は、あなたの後にある可能性があります。また、半ガウス分布(統計的なベルカーブ、ゼロエントリーを切り捨て、おそらく分布の極端なテールも範囲外になる)を使用することができます。

正解はありません。さまざまなことを試し、1万ほどの値をプロットし、好きな結果を与えるものを選んでください。

関連する問題