C++ 概率规划
在我们需要生成概率的情况下,例如,一个有75%的头部和25%的尾部摆动的偏向硬币。按照惯例,我会这样做:C++ 概率规划,c++,algorithm,math,random,probability,C++,Algorithm,Math,Random,Probability,在我们需要生成概率的情况下,例如,一个有75%的头部和25%的尾部摆动的偏向硬币。按照惯例,我会这样做: #include <cstdlib> #include <iostream> #include <ctime> using namespace std; int main() { int heads=0, tails=0; srand(time(NULL)); number = rand() % 100 + 1; //Gener
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int heads=0, tails=0;
srand(time(NULL));
number = rand() % 100 + 1; //Generate random number 1 to 100
if (number <= 75) //75% chance
heads++; //This is head
else
tails++; //This is tail
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
int头=0,尾=0;
srand(时间(空));
number=rand()%100+1;//生成随机数1到100
如果(数字)
上述代码是否可用于创建模拟
概率?或者这些代码中是否存在任何会影响
模拟结果的准确性如何
如果这是“可接受的”,这取决于您对可接受的定义。这肯定是不正确的,因为运算符%会使您的概率发生偏差,因为RAND_MAX是RAND()的最大值
不能等于k*100+99,这导致如果您想象0-RAND_MAX字符串的100个长度部分,那么您可以看到最后一部分可能不会生成完整的0-99范围,因此您有更多的数字生成0,1,2…,x,但不需要x+1…,98,99(0,1,2,…,x中的每个数字多出现1次)。这种方法的不准确度随着除数的增大而增加,除数不能均匀地划分范围
如果上述代码有缺陷,正确的解决方法是什么
实现概率模拟
您可以使用boost,或者如果您可以运行C++11,那么您可以使用标准库。使用rand()%100+1
的工作方式与“生成100个随机数时,正好75个数将小于75”的工作方式不同
换句话说,它不能保证在100个随机生成的数字中,75个数字将小于75!由于数字的有限性,您总是会得到有偏差的结果(增加随机数生成器的结果数将提高准确性)
在您的样本中,您可能对什么是75%有更好的定义:
int main()
{
int heads=0, tails=0;
srand(time(NULL));
const std::size_t Samples = 10000000;
for(std::size_t i = 0; i < Samples; ++i) {
int head_limit = RAND_MAX * 0.75;
int number = rand();
if (number <= head_limit) heads++;
else tails++;
}
// heads: 7498728 [0.749873%]
// tails: 2501272 [0.250127%]
std::cout
<< "heads: " << heads << " [" << double(heads) / Samples << "%]\n"
<< "tails: " << tails << " [" << double(tails) / Samples << "%]\n";
}
intmain()
{
int头=0,尾=0;
srand(时间(空));
const std::size\u t Samples=10000000;
对于(标准::尺寸\u t i=0;i
我不知道您对“可接受”的定义。但是,我会避免使用rand()
,请参见示例
如果上面的代码有缺陷,那么实现模拟的正确方法是什么
概率
我会使用。它质量高、速度快(根据Stephan T.Lavavej的介绍)而且标准
顺便说一下,std::bernoulli_分布的示例代码给出了时间的“真”1/4和“假”3/4;std::rand()
假设RAND_MAX
被定义为32767,将RAND()%100
生成平面分布?否。从0到32699,0到99的每个值将显示327次。但是从32700到32767,0到67的值显示一次,68-99的值显示0次。因此,您的分布有328次00-67,327次68-99
此外,除非您以某种方式指定RAND_MAX是什么,或者在代码中使用它,否则编译器实现对RAND_MAX使用的任何东西都将影响您,并且您的分布将以某种未知的方式发生倾斜
如果你想要一枚硬币在四分之三的时间里出现,考虑这样的事情:
if((double)std::rand()/3.0 > (double)RAND_MAX/4.0)
bool trial (int randList[], const int SIZE, int trialCount)
{
return (randList[trialCount % SIZE] < 75); // Head = True = 75%
}
(如果a>3/4*b,那么a/3>b/4)。这几乎是公平的;RAND_MAX不太可能整齐地划分为4。但这比原始代码中的1/327偏差要好
但更好的是,使用更好的随机数生成器,您可以在其中设置限制。为了确保1到100或0到99之间的每个数字都有一个概率p=1/100,以确保您有准确的概率排序
然后,不是使用随机生成的数字,而是使用1000个1-100个均匀分布的列表,然后每次需要重复使用它们时,使用相同的随机数生成器将它们洗牌
因此,首先我们要建立一个列表:
const int SIZE = 1000;
srand(time(NULL));
int randList [SIZE];
void shuffle (int randList[], const int SIZE)
{
for (int i=0; i<SIZE; i++)
swap(randList,i,(rand() % SIZE));
}
void swap (int randList[], int a, int b)
{
int t = randList[a];
randList[a] = randList[b];
randList[b] = t;
}
然后我们填写:
void init (int randList[], const int SIZE)
{
for (int i=0; i<SIZE; i++)
randList[i] = i % 100;
}
“因为随机函数生成正态分布”-不,它不生成正态分布。它生成一个均匀分布,%
运算符使分布倾斜。@MitchWheat是的,我的意思是均匀分布,我将对此进行编辑。谢谢:-)Bethsheba对您链接的问题的回答充分解释了为什么不赞成使用%的原因。rand()与模数结合使用有已知缺陷,不要用于任何重要的东西,例如证明。使用10000000个样本(至少,使用动态内存)只需加上它,(MAX\u INT%100)
不是零,(我不确定rand()
的分布情况如何,但考虑到它是0到MAX_INT的统一分布,您只需使用rand()%4
并检查是否小于4(您希望以2的幂进行修改)。
void test (bool * resultList, const int resultSize)
{
const int SIZE = 1000;
srand(time(NULL));
int randList [SIZE];
init(randList,SIZE);
for (int i=0; i<resultSize; i++)
{
if (i%SIZE == 0)
shuffle(randList,SIZE);
resultList[i] = trial(randList,SIZE,i);
}
}
int main ()
{
const int resultSize = 2000000; // 2 Million
bool * resultList = new bool[resultSize];
test(resultList,resultSize);
// check sequence of outcomes
return 0;
}