我正在尝试在c ++中编写一个函数,它将根据给定的概率返回true或false。因此,例如,如果给定的概率是0.634,那么63.4%的函数将返回true。我尝试了一些不同的东西,但都失败了。有帮助吗?
答案 0 :(得分:14)
如果您想在C ++ 11中执行此操作,可以使用其各种随机数引擎,并结合uniform_real_distribution
来提供良好的结果。以下代码演示了:
#include <random>
std::knuth_b rand_engine; // replace knuth_b with one of the engines listed below
std::uniform_real_distribution<> uniform_zero_to_one(0.0, 1.0);
bool random_bool_with_prob( double prob ) // probability between 0.0 and 1.0
{
return uniform_zero_to_one(rand_engine) >= prob;
}
或者,您可以使用bernoulli_distribution
,它会直接为您提供具有指定概率的bool
。它所需的概率是返回true的概率,所以它正是你所需要的:
#include <random>
std::knuth_b rand_engine; // replace knuth_b with one of the engines listed below
bool random_bool_with_prob( double prob ) // probability between 0.0 and 1.0
{
std::bernoulli_distribution d(prob);
return d(rand_engine);
}
如果您的概率是固定的,那么您可以将其移出函数,如下所示:
#include <random>
std::knuth_b rand_engine; // replace knuth_b with one of the engines listed below
std::bernoulli_distribution random_bool_generator( prob ); // replace "prob" with your probability
bool random_bool()
{
return random_bool_generator( rand_engine );
}
或者如果你想要更加漂亮,你可以将它们绑在一起:
#include <random>
#include <functional>
std::knuth_b rand_engine; // replace knuth_b with one of the engines listed below
std::bernoulli_distribution random_bool_generator( prob ); // replace "prob" with your probability
auto random_bool = std::bind( random_bool_generator, rand_engine )
// Now call random_bool() to get your random boolean with the specified probability.
您可以将knuth_b
替换为任何标准引擎:
std::linear_congruential_engine
std::mersenne_twister_engine
std::subtract_with_carry_engine
或更多,以上的版本,参数化各种方式。我的参考文献列出了以下内容:
std::default_random_engine
(已定义实施。)std::minstd_rand0
std::minstd_rand
std::mt19937
std::mt19337_64
std::ranlux24_base
std::ranlux48_base
std::ranlux24
std::ranlux48
std::knuth_b
如果这还不够,有一些标准适配器可以进一步扰乱随机数序列:
std::discard_block_engine
通过每次丢弃给定数量的生成值来调整引擎。std::independent_bits_engine
,它调整引擎以产生具有指定位数的随机值。 (对您的特殊需求并不重要。)std::shuffle_order_engine
通过排列生成值的顺序来调整引擎。第二个列表中的生成器派生自第一个列表中的基本生成器,具有特定参数,适配器或两者。例如,根据我的参考书,knuth_b
相当于shuffle_order_engine< linear_congruential_engine< uint32_t, 16807, 0, 2147483647>, 256>
。 ( C ++标准库,第二版,Nicolai Josuttis,一篇很棒的参考书。)
您可以在线找到更多信息,包括此简介:http://en.wikipedia.org/wiki/C++11#Extensible_random_number_facility
此处有更多文档:http://en.cppreference.com/w/cpp/numeric/random
您可能希望修改上面rand_engine
的声明以提供种子。上面的示例使用默认种子。如果你想要一个不同的种子,请参阅cppreference.com了解如何播种它。
答案 1 :(得分:3)
#include <stdlib.h>
bool prob_true(double p){
return rand()/(RAND_MAX+1.0) < p;
}
逻辑:
rand()
会在0
和RAND_MAX
之间返回一个随机数(包括两者),每个数字的概率相等。因此,通过将结果除以RAND_MAX
,我们得到0
和1
之间的随机数。这允许我们选择一个区域 - 在您的示例中该区域的63.4%,例如从0
到0.634
- 并检查结果是否落在该区域。
现在出现了棘手的部分:我们不想同时获得0
和1
!为什么?因为我们希望概率0
永远不会成立,所以我们需要<p
(而不是<=p
) - 所以当p=0
时你永远不会成真。
但是,如果您也可以1
作为结果,那么在p=1
的情况下,您获得错误的可能性非常小!
这就是为什么而不是除以MAX_RAND
除以MAX_RAND+1.0
。另请注意,我添加了1.0
而不是1
来将数字转换为双数(否则,如果MAX_RAND==INT_MAX
我可能会出现溢出)
最后,这是一个没有划分的替代实现:
#include <stdlib.h>
bool prob_true(double p){
return rand() < p * (RAND_MAX+1.0);
}