我想知道是否有办法在A和b之间有一个随机数,如果一个数字满足某个要求,它比A和B之间的所有其他数字更可能出现,例如:数字较低如果A = 1且B = 10则更有可能出现,那么1将是最有可能的,10将是最不可能的。
所有帮助表示赞赏:)(抱歉英语/语法/问题不好)
答案 0 :(得分:2)
C ++ 11(您现在绝对应该使用它)将<random>
标头添加到C ++标准库中。此标头为C ++提供了更高质量的随机数生成器。使用srand()
和rand()
从来就不是一个好主意,因为不能保证质量,但现在它确实是不可原谅的。
在你的例子中,听起来你想要的可能被称为“离散三角分布”:概率质量函数看起来像一个三角形。在C ++中实现它的最简单(但也许不是最有效)的方法是<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.
使用现有的一个发行版(我已经被告知所有常用的统计发行版都包括在内)或者编写自己的发行版时,使用比这更复杂的东西会更好:这不是太难:它只是必须是一个带有函数调用运算符的对象,它接受一个随机位生成器并使用这些位生成(在这种情况下)随机数。但你可以创建一个随机字符串或任意随机对象,可能用于测试目的。)
答案 1 :(得分:2)
您的问题未指定要使用的分配。一个选项(很多)是使用(negative) exponential distribution。该分布由参数λ参数化。对于λ的每个值,最大结果是无界的(需要处理以便仅在指定的范围内返回结果)
(来自维基百科,By Skbkekas,CC BY 3.0)
所以λ理论上可以起作用;但是,CDF的属性
(来自维基百科,By Skbkekas,CC BY 3.0)
暗示按 1 /(从 - + 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
++++++++++
+++++++++
+++++++++
++++++++
+++++++
+++++++
+++++++
+++++++
++++++
++++++
答案 2 :(得分:0)
您的基本随机数生成器应在0到1 - epsilon上生成高质量,均匀的随机数。然后转换它以获得所需的分发。当然,在需要0到N -1的整数的常见情况下,最简单的变换是(int)(p * N)。
但是你可以尝试许多其他变换。以平方根为例,将其偏向1.0,然后以1-p将偏差设为零。或者你可以查找泊松分布,这可能就是你所追求的。您还可以使用半高斯分布(统计钟形曲线,零条目被切断,并且可能也是分布的极端尾部,因为它超出范围)。
没有正确答案。尝试各种各样的事情,绘制出一万个左右的值,然后选择一个给出你喜欢的结果。
答案 3 :(得分:-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];
此外,您可以尝试两次随机数,第一次选择最大数字然后选择随机数:
int max= rand() % 10 + 1; // This is your max value
int random = rand() % max + 1; // This is you result
两种方式的可能性都比2提高1,比3提高2的可能性高出10 ...。