java - 在 Java 中使用随机生成的数据对 pi 进行蒙特卡洛计算

标签 java random montecarlo pi

我正在开发一个程序,该程序根据随机生成的 float 来计算 pi,这些 float 表示图形上的 x,y 坐标。每个 x, y 坐标都以 2 的次方为基础,并存储在两个单独的数组中。坐标均匀分布在0,1区间的图形上。

程序将 x、y 坐标相加,如果它们小于 1,则这些点位于直径为 1 的圆内,如下图所示。

enter image description here

然后我使用了这个公式,

π ≈ 4 w/n

计算圆周率。其中,w 是圆内点的数量,n 是数组内 x 或 y 坐标的数量。

当我将 n 设置为 10,000,000(数组的大小)时,它会生成 15-16 位小数的最准确的 pi 计算。然而,在将 4GB RAM 专用于运行配置并将 n 设置为 100,000,000 pi 后最终为 0.6710...

我想知道为什么会发生这种情况?对不起,如果这是一个愚蠢的问题..代码如下。

import java.text.DecimalFormat;
import java.util.Random;

public class random_pi {

    public random_pi() {

        float x2_store[] = new float[10000000];
        float y2_store[] = new float[10000000];
        float w = 0;

        Random rand = new Random();
        DecimalFormat df2 = new DecimalFormat("#,###,###");

        for (int i = 0; i < x2_store.length; i++) {
            float x2 = (float) Math.pow(rand.nextFloat(), 2);
            x2_store[i] = x2;
            float y2 = (float) Math.pow(rand.nextFloat(), 2);
            y2_store[i] = y2;
        }

        for (int i = 0; i < x2_store.length; i++) {
            if (x2_store[i] + y2_store[i] < 1) {
                w++;
            }
        }

        System.out.println("w: "+w);
        float numerator = (4*w);
        System.out.printf("4*w: " + (numerator));
        System.out.println("\nn: " + df2.format(x2_store.length));
        float pi = numerator / x2_store.length;

        String fmt = String.format("%.20f", pi);
        System.out.println(fmt);

        String pi_string = Double.toString(Math.abs(pi));
        int intP = pi_string.indexOf('.');
        int decP = pi_string.length() - intP - 1;
        System.out.println("decimal places: " + decP);
    }

    public static void main(String[] args) {
        new random_pi();
    }
}

最佳答案

问题在这里:

float w = 0;
float numerator = (4*w);

float精度不够,改成intdouble:

喜欢这个工作示例代码:

import java.text.DecimalFormat;
import java.util.Random;

public class random_pi {

    public random_pi() {

        float x2_store[] = new float[100000000];
        float y2_store[] = new float[100000000];
        int w = 0;

        Random rand = new Random();
        DecimalFormat df2 = new DecimalFormat("#,###,###");

        for (int i = 0; i < x2_store.length; i++) {
            float x2 = (float) Math.pow(rand.nextFloat(), 2);
            x2_store[i] = x2;
            float y2 = (float) Math.pow(rand.nextFloat(), 2);
            y2_store[i] = y2;
        }

        for (int i = 0; i < x2_store.length; i++) {
            if (x2_store[i] + y2_store[i] < 1) {
                w++;
            }
        }

        System.out.println("w: "+w);
        int numerator = (4*w);
        System.out.printf("4*w: " + (numerator));
        System.out.println("\nn: " + df2.format(x2_store.length));
        float pi = ((float)numerator) / x2_store.length;

        String fmt = String.format("%.20f", pi);
        System.out.println(fmt);

        String pi_string = Double.toString(Math.abs(pi));
        int intP = pi_string.indexOf('.');
        int decP = pi_string.length() - intP - 1;
        System.out.println("decimal places: " + decP);
    }

    public static void main(String[] args) {
        new random_pi();
    }
}

输出:

w: 78544041
4*w: 314176164
n: 100,000,000
3.14176154136657700000
decimal places: 15

而且您不需要存储结果,就像这个工作示例代码一样:

import java.text.DecimalFormat;
import java.util.Random;

public class pi {

    public pi() {
        double n=100000000; 
        double w = 0;

        Random rand = new Random();
        DecimalFormat df2 = new DecimalFormat("#,###,###");

        for (int i = 0; i < n; i++) {
            double x = rand.nextFloat(); 
            double y = rand.nextFloat();  
            if ((x*x + y*y) < 1.0) w++;
        }

        System.out.println("w: "+w);//w: 7852372.0
        double numerator = (4*w);
        System.out.printf("4*w: " + (numerator));//4*w: 3.1409488E7
        System.out.println("\nn: " + df2.format(n));//n: 10,000,000
        double pi = numerator / n;

        final String fmt = String.format("%.20f", pi);
        System.out.println(fmt);//3.14094877243042000000

        String pi_string = Double.toString(Math.abs(pi));
        int intP = pi_string.indexOf('.');
        int decP = pi_string.length() - intP - 1;
        System.out.println("decimal places: " + decP);//decimal places: 14
    }

    public static void main(String[] args) {
        new random_pi();
    }
}

输出:

w: 78539606
4*w: 314158424
n: 100,000,000
3.14158439636230470000
decimal places: 16

关于java - 在 Java 中使用随机生成的数据对 pi 进行蒙特卡洛计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38928988/

相关文章:

javascript - 选择随机数组,然后选择该数组中的一个元素

android - 关于 Firestore 中查询的随机结果

c++ - c++中蒙特卡洛方法的好书?

python - 重置Series索引而不转为DataFrame

Java Web App插入mysql,最好的方法

java - 从附加的 OnPreDrawListener 对象中获取 ViewTreeObserver 对象

java - 有效方法不适用于 Netbeans RCP 平台上的自定义选项面板

c++ - Mersenne Twister 种子没有效果

python - 在 Python 中利用蒙特卡洛预测收入

java - Java耗时过长如何成功销毁进程?