当获得0的概率为10%,1为7%且获得其余数字的概率相等时,如何使用rand()
函数在C ++中生成0到100之间的随机数? / p>
答案 0 :(得分:3)
rand()
功能可能是在这里完成工作的错误工具。 C ++,因为C ++ 11有(伪)随机数生成的新工具:http://en.cppreference.com/w/cpp/numeric/random这些工具中有RandomNumberDistribution的概念,其中一个分发由std::discrete_distribution提供。 std :: discrete_distribution允许您定义分布中数字的权重,以便不同的数字可以具有不同的预定义概率。
#include <iostream>
#include <map>
#include <random>
#include <cmath>
int main()
{
std::random_device r;
std::default_random_engine e1(r());
// Distribution that defines different weights (17, 10, etc.) for numbers.
std::discrete_distribution<int> discrete_dist({17, 10, 5, 3, 1});
// The map keeps track of number of occurences for each value.
std::map<int, int> histogram;
for (int n = 0; n < 100; ++n) {
++histogram[std::round(discrete_dist(e1))];
}
std::cout << "Distribution:\n";
for (auto p : histogram) {
std::cout << p.first << ' ' << p.second << '\n';
}
}
输出可能类似于:
Distribution:
0 51
1 23
2 13
3 9
4 4
答案 1 :(得分:0)
您可以使用std :: uniform_real_distribution以及间隔表来执行此类查找。
我们可以做的是生成一个从0.0到1.0的数字,并使用一种查找表将其映射到整数空间。
例如:
#include <random>
#include <vector>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <map>
struct TableEntry
{
double upper_bound = 0.0f;
int value = 0;
//for std::is_sorted, std::Upper_bound;
bool operator<(TableEntry const& other) const
{
return this->upper_bound < other.upper_bound;
}
};
struct Generator
{
Generator():
gen(std::random_device()()), //seed the random number generator
dis(0.0, 1.0) //we want a value between - and 1
{
break_table.push_back({0.1, 0}); //10 percent probability of yielding 0
break_table.push_back({0.17, 1}); // (0.17 - 0.1) == 7% chance of yielding 1
//fill in the rest of the table uniformly
double step = (1.0 - 0.17)/98; //98 values remaining, distribute equally
for(int i = 2; i < 100; i++)
{
break_table.push_back({0.17 + (i-1)*step, i});
}
assert(std::is_sorted(begin(break_table), end(break_table)));
assert(abs(break_table.back().upper_bound - 1.0) < 0.00001);
}
//call the object as a function to get a value
int operator()()
{
double bval = dis(gen); //bval is in interval [0, 1);
// std::upper_bound returns an iterator to the first value bigger than bval
auto break_entry = std::upper_bound(begin(break_table), end(break_table), TableEntry{bval, 0});
//special case: we're off the end of the scale
if(break_entry == end(break_table)) return break_table.back().value;
else return break_entry->value;
};
private:
std::vector<TableEntry> break_table;
std::mt19937 gen;
std::uniform_real_distribution<double> dis;
};
int main()
{
Generator g;
//verify the probabilities
const size_t N = 10'000'000;
std::map<int, size_t> number_counts; // keep track of occurences of each number
for(size_t i = 0; i < N; i++)
{
int v = g();
number_counts[v]++;
}
for(auto const& kv: number_counts)
{
double p = static_cast<double>(kv.second) / N;
std::cout << kv.first << " : " << p * 100.0 << "%\n";
}
return 0;
}
运行此代码后,我得到以下分布:
0 : 10.0069%
1 : 7.01544%
2 : 0.84899%
3 : 0.84358%
4 : 0.8462%
5 : 0.84468%
6 : 0.85324%
7 : 0.85023%
8 : 0.85003%
9 : 0.84862%
...
99 : 0.84219%
......看起来很不错。