使用C查找pi的蒙特卡洛方法

时间:2019-03-13 18:19:39

标签: c montecarlo pi

我编写了一个函数,该函数采用长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;
}

5 个答案:

答案 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)

您的randomxrandomy变量被约束为 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);
    }