我编写了一个函数,该函数采用长long值n
,并将其用作要经历的迭代次数。该函数应该可以很好地估计pi,但是,大n
的所有值都趋向于3.000,而不是3.1415,所以我不确定会发生什么?
我做错了什么吗?
这是我的代码:
double estimate_pi(long long n){
double randomx, randomy, equation, pi;
long long i, incircle = 0;
for(i = 0; i < n; i++){
randomx = (double)(rand() % (1+1-0) + 0);
randomy = (double)(rand() % (1+1-0) + 0);
equation = randomx * randomx + randomy * randomy;
if(equation <= 1){
incircle++;
}
}
pi = (long double)4 * (long double)incircle / (long double)n;
return pi;
}
在主函数中,打印pi的10个值:
int main(void){
long long N;
double pi_approx;
int i;
printf("Input a value of N: ");
if(scanf("%ld", &N) != 1){
printf("Error, input must be an integer!\n");
exit(EXIT_SUCCESS);
}
if(N < 1){
printf("Error, the integer must be positive!\n");
exit(EXIT_SUCCESS);
}
srand(time(NULL));
for(i = 0; i < 10; i++){
pi_approx = estimate_pi(N);
printf("%.10f\n", pi_approx);
}
return 0;
}
答案 0 :(得分:6)
它可以正常工作。问题是实现。
C rand()
函数returns an integer的范围是0到RAND_MAX
。那里的关键字是整数。
然后,您可以计算该整数模2的结果,该整数可以为0或1。这将为您留下4个可能的点:(0,0),(0,1),(1,0),(1, 1)。
在这4个点中,只有1个位于半径1:(1,1)的圆之外。也就是说,在4个可能的点中,有3个位于圆圈中。
您应该替换该代码以使用浮点值,而不是整数,以便计算圆内外的点比例。
答案 1 :(得分:5)
您需要使用浮点随机化,否则要使用半径很大的圆。
所以不是
randomx = (double)(rand() % (1+1-0) + 0);
randomy = (double)(rand() % (1+1-0) + 0);
您使用
randomx = rand();
randomy = rand();
,然后考虑它是否在半径RAND_MAX的圆之内
#define RMAX ((double)RAND_MAX*(double)RAND_MAX)
equation <= RMAX;
您要执行详细信息。阅读man 3 rand
以查看rand()返回整数。
答案 2 :(得分:3)
您的randomx
和randomy
变量被约束为 integer 值,因为rand()
函数返回一个整数。
实时观看here。
因此,您的两个变量每个将为1或0,因此您的点将随机为(0,0),(1,0),(0,1),(1,1),就有3:4的机会进入圈子。因此,您的结果为3。
如果您想要一个介于0和1之间的随机数,则可以查询How to generate random float number in C。
答案 3 :(得分:2)
对于您的工作方式,您需要生成double
值,该值是从间隔[0,1](或大约间隔)的均匀分布中得出的。相反,您将从两个元素集{0,1}中提取随机整数,并将其转换为类型double
。这不会产生像您所需的发行版那样的远程内容。
答案 4 :(得分:0)
其他人已经指出了你的错误。我提供优化版本 based on another SO Thead
int main(void)
{
long points = 1000000000; // Some input
long m = 0;
unsigned long HAUSNUMERO = 1;
double DIV1byMAXbyMAX = 1. / RAND_MAX / RAND_MAX;
unsigned int aThreadSpecificSEED_x = HAUSNUMERO + 1
unsigned int aThreadSpecificSEED_y = HAUSNUMERO - 1
for(long i = 0; i < points; i++)
{
double x = rand_r( &aThreadSpecificSEED_x );
double y = rand_r( &aThreadSpecificSEED_y );
m += (1 >= ( x * x + y * y ) * DIV1byMAXbyMAX);
}
printf("Pi is roughly %lf\n", (double) 4*m / (double) points);
}