問題は、 rand() がドメイン上で均一に分散された変数を提供すること[0,RAND_MAX]
でありRAND_MAX
、最も可能性が高いのは 32767 です。単純な乗算によって、このドメインをより大きなドメインにマップすることはできません。
u=(double)rand();
d=(double)RAND_MAX;
double div= u/d;
double res=div*interval_range;
これは、RAND_MAX が の偶数倍である場合にのみ正しいためですinterval_range
。ただし、その場合、より大きなドメインにすべての値があるわけではありません。ただし、新しい目的のドメインがRAND_MAX
あなたの場合よりも小さい場合は、によって生成された一様分布をrand()
目的のドメインに切り詰めることができます (本質的にrand()
、目的のドメインよりも大きい値を拒否することを意味します)。切り捨てられた一様分布はまだ一様であるため、新しいドメインに新しい一様分布変数があります (これはより正確には条件付き分布になります)。統計例:
したがって、切り捨てられた一様分布には別の「瞬間」、それを説明するパラメーター (平均、std_dev、分散など) がありますが、再び一様になります。
コード例:
int main{
int o=RAND_MAX;
std::map<int,int> m1;
int min=0,max=999;
for (int i=0; i<1000*9994240; ++i){//9994240=305*32768 32768=RAND_MAX+1
int r=rand();
if(r<=max){
m1[r]++;
}
}
for (auto & i : m1)
std::cout << i.first << " : " << i.second << '\n';
}
結果:0:42637 1:42716 2:42590 3:42993 4:42936 5:42965 6:42941 7:42705 8:42944 9:42707 10:42860 11:43012 12:42793 // ... 995:42861 996 : 42911 997 : 42865 998 : 42877 999 : 43159
この方法で、任意のドメインで目的の結果を得ることができます。
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 1000);
for (int n=0; n<1000; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
ただし、この場合は実際にブーストを使用する必要があります。
#include <iostream>
#include "boost/random.hpp"
#include "boost/generator_iterator.hpp"
using namespace std;
int main() {
typedef boost::mt19937 RNGType;
RNGType rng;
boost::uniform_int<> zero_to_n( 0, 999 );
boost::variate_generator< RNGType, boost::uniform_int<> >
dice(rng, zero_to_n);
int n = dice();
}