我在想是否有一种方法可以在A和B之间生成随机数,并且如果一个数符合特定要求,则它比A和B之间的所有其他数字更有可能出现,例如:较小的数字更有可能出现,因此如果A = 1且B = 10,则1将是最可能出现的数字,而10则是最不可能出现的数字。非常感谢您的帮助 :)(对于糟糕的英语/语法/问题表示抱歉)
<random>
头添加到C++标准库中。此头文件为C++提供了更高质量的随机数生成器。使用srand()
和rand()
从来都不是一个好主意,因为没有保证其质量,但现在这已经变得不可原谅了。<random>
中包含的离散分布。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";
}
对我来说,这会产生以下输出:
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.
对于比这更复杂的事情,最好使用现有的分布之一(据我所知,所有常用的统计分布都已包含在内),或者编写自己的分布。编写自己的分布并不难:它只需要是一个对象,具有一个函数调用运算符,该运算符接受一个随机比特生成器,并使用这些比特产生(在本例中)随机数。但是您可以创建一个生成随机字符串或任何任意随机对象的分布,也许是为了测试目的。
#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到1-epsilon范围内产生高质量、均匀分布的随机数。然后,你可以进行转换以得到所需的分布。最简单的转换当然是 (int) ( p * N ),通常需要整数范围为0 到N -1。
但还有许多其他的转换方法可供尝试。例如,取平方根来偏向于1.0,然后取 1-p 来设置向0的偏差。或者你可以查找泊松分布,这可能是你想要的。你也可以使用半高斯分布(统计钟形曲线,将零条目切断,并且可能还有分布的极端尾巴超出范围)。
没有正确答案。尝试各种各样的方法,绘制出大约一万个值,并选择结果你喜欢的一个。
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];
此外,您可以尝试获取两次随机数,第一次选择最大数,然后选择您的随机数:
int max= rand() % 10 + 1; // This is your max value
int random = rand() % max + 1; // This is you result