【发布时间】:2017-10-01 19:18:55
【问题描述】:
我正在使用这种粗略的蒙特卡洛积分技术来找出 $\pi$ 的值,并注意到随着样本点数量的增加,积分值逐渐偏离实际值。代码是:
#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
float f(float x)//definition of the integrand
{
return sqrt(1-x*x);
}
float rand1()//random number generator between 0 and 1
{
float s=rand();
return s/(RAND_MAX+1.0);
}
float calcint(float xi,float xf,float yi,float yf,float N)//integrator
{
float n=0;
for(int i=0;i<N;i++)
{
float x=(xf-xi)*rand1();float y=(yf-yi)*rand1();
if (y<f(x))
{
n=n+1;
}
}
return n/N*(xf-xi)*(yf-yi);
}
int main()
{
float N=100000000;
for (int i=1; i<N; i=i+N/10)//lists integration value for different sampling
{
cout<<i<<"\t"<<4*calcint(0,1,0,1,i)<<endl;
}
return 0;
}
输出是,
10000000 3.14188
20000000 3.14059
30000000 2.23696
40000000 1.67772
50000000 1.34218
60000000 1.11848
70000000 0.958698
80000000 0.838861
90000000 0.745654
为什么会这样?蒙特卡洛积分技术能否保证在大量样本点上收敛?
【问题讨论】:
-
首先,当
N为 0 时,您在calcInt中除以 0。其次,您正在混合 float 和 int ,预计不会损失精度。 -
我解决了第一个问题。但我看不到我在哪里混合int和float。我只是在 for 语句的条件下比较它们。我并没有真正转换它们。您能否详细说明这可能会如何影响结果?为什么它们会稳步下降?如果在比较过程中可能发生转换问题,那么结果应该突然减小到一个值并保持在那里。
-
离题:
if (y < f(x))可以表示为if (y * y < 1 - x * x)。 -
您在 1)
for循环限制i=i+N/102) 您对calcInt的调用(查看最后一个参数)。您正在转换它们,即使不是明确的。 -
@PaulMcKenzie 我看到了这些转换,但它们仍然没有解释为什么集成值会下降。请参阅接受的答案,我应该将
n声明为整数,或与N具有相同类型。否则,n 会停止增加,但 N 会增加,这会导致错误(更小)的 n/N 值。无论如何,感谢您的努力。我很感激。
标签: c++ montecarlo