我正在尝试使用蒙特卡罗方法计算PI。无论MAXLEN有多大,我的代码都会给出结果3.000。经过多次调试后,我无法得到我做错的事。
#include <stdio.h>
#include <stdlib.h>
#define sqr2(x) ((x)*(x))
#define frand() ((double) rand() / (RAND_MAX))
#define MAXLEN 1000
int circumscribed(int radius){
float xcoord = frand();
float ycoord = frand();
float coord = sqr2(xcoord) + sqr2(ycoord);
if(coord <= radius)
return 1;
return -1;
}
int main()
{
int i;
int circles = 0, rect = 0;;
for(i = 0; i < MAXLEN; i++)
{
if(circumscribed(1) > 0) // if(circumscribed(1)) shoul be enough but it doesn't work. Very odd in my opinion.
circles++;
rect++; //this is equal to MAXLEN, I just used it for debugging
}
float PI = 4 * circles / rect;
printf("PI is %2.4f: \n", PI);
return 0;
}
答案 0 :(得分:5)
由于circles
和rect
都是int
,4 * circles / rect
的结果将是int
。请改用浮点数。
float PI = 4.0 * (float)circles / rect;
答案 1 :(得分:2)
这个表达式都是整数:
4 * circles / rect;
因此,结果是整数(在这种情况下为3)。
(作为类似示例:10 / 3 == 3
,但10.0 / 3.0 == 3.333333
)
尝试改为:
4.0 * circles / rect;
只需将(int)4
更改为(double)4
,将其称为4.0
甚至4.
就足够了。
<小时/> 其他杂项观察
这一行有一个额外的分号:
int circles = 0, rect = 0;;
您的功能circumscribed
使用float
。您的变量PI
也是float
。
如果您使用double
,您将获得更高的精确度。
答案 2 :(得分:2)
你在这里integer Math
。您的代码中circles
和rect
都是int
,因此4 * circles / rect
的结果也是int
。请改用浮点数。使用double
可获得更好的精确度。
double PI = 4.0 * (double)circles / rect;
答案 3 :(得分:1)
答案 4 :(得分:1)
float PI = 4 * circles / rect;
这会在=
的右侧执行整数运算,从而将结果限制为1位有效数字。
相反:
double PI = 4.0 * circles / rect; // Best
详细
float PI = 4.0 * (float)circles / rect; // OK
建议避免使用float
。请改用double
以避免将此蒙特卡罗限制为大约7位数。当circles
变大时,它可能无法完全转换为相同的float
值。相反,它会转换为四舍五入的float
。这发生在大约circles
&gt;许多机器上有8,000,000个。通过舍入,您可以不必要地限制可达到的精度。使用double
,在circles
大约为9e15之前不会进行此舍入。
float PI = 4.0 * (double) circles / rect; // Better
(double) circles
的显式转换可能对读者有用,但无论是否有代码,代码都会以相同的方式执行。 4.0是一个double
,即使没有强制转换,也会在多重性发生之前导致double
升级到circles
。
double PI = 4.0 * circles / rect; // Better
由于4.0 * ...
结果为double,因此通过保存为double可保留最佳精度。使用float PI
会导致乘法/除法,这是以双精度完成的,以降低保存到浮点数时的精度。
float or double PI = ...
printf("PI is %2.4f: \n", PI);
注意:此处,无论PI是PI
还是printf()
,都会将float
转换为double
传递给{{1}}。因此可以通过将其声明为两倍来访问PI中的精度。
注意:int,float和double范围和精度取决于机器。以上反映了一种常见的实施方式。
答案 5 :(得分:0)
查看此代码:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define SEED 35791246
int main(int argc, char** argv)
{
int niter=0;
double x,y;
int i,count=0; /* # of points in the 1st quadrant of unit circle */
double z;
double pi;
printf("Enter the number of iterations used to estimate pi: ");
scanf("%d",&niter);
/* initialize random numbers */
srand(SEED);
count=0;
for ( i=0; i<niter; i++) {
x = (double)rand()/RAND_MAX;
y = (double)rand()/RAND_MAX;
z = x*x+y*y;
if (z<=1) count++;
}
pi=(double)count/niter*4;
printf("# of trials= %d , estimate of pi is %g \n",niter,pi);
return 0;
}