使用蒙特卡罗方法计算PI给出了不精确的答案

时间:2013-07-15 16:57:01

标签: c pi

我正在尝试使用蒙特卡罗方法计算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;   
}

6 个答案:

答案 0 :(得分:5)

由于circlesrect都是int4 * 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。您的代码中circlesrect都是int,因此4 * circles / rect的结果也是int。请改用浮点数。使用double可获得更好的精确度。

double PI = 4.0 * (double)circles / rect;

答案 3 :(得分:1)

您在此处执行整数数学:

float PI = 4 * circles / rect;

4更改为4.0足以解决问题:

float PI = 4.0 * circles / rect;

工作版here

答案 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;
}