我正在尝试着名的蒙特卡罗模拟来估算我的Java课程的pi。 这是模拟:
public class Darts
{
//"throwing" a dart
public static boolean [] dartThrow(int r, int d){
boolean [] booleanArray = new boolean[d];
for(int i = 0; i < d; i++){
double xCoord = Math.random() * 2;
double yCoord = Math.random() * 2;
if((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= r){
booleanArray[i] = true;
}
else{
booleanArray [i] = false;
}
}
return booleanArray;
}
//calculating pi from throwing results
public static double piEstimater(boolean [] h, int d){
int trueCounter = 0;
for(int i = 0; i < h.length; i++){
if(h[i] == true){
trueCounter++;
}
}
return 4 * ((double)trueCounter / d);
}
//printing results
public static void printer(double [] a){
System.out.println(" Pi Estimation Tool ");
System.out.println("---------------------------");
for(int i = 0; i < a.length; i++){
System.out.print("Trial [" + i + "]: pi = ");
System.out.printf("%6f\n", a[i]);
}
}
public static void main(String[] args){
//variables
Scanner in = new Scanner(System.in);
int radius = 1;
int darts;
int trials;
System.out.println("Enter the number of darts to calculate for: ");
darts = in.nextInt();
System.out.println("Enter the number of trials to calculate for: ");
trials = in.nextInt();
double [] arrayOfEstimates = new double [trials];
int i = 0;
for(double a : arrayOfEstimates){
boolean [] hitCounter = dartThrow(radius, darts);
double piEstimate = piEstimater(hitCounter, darts);
arrayOfEstimates[i] = piEstimate;
i++;
}
printer(arrayOfEstimates);
}
}
我已经创建了正确执行的代码,除了结果永远不会超过〜.8。我想假设这种情况正在发生,因为随机数是如此之低,但如果每次出现错误都会发生,对吧?请记住,这段代码包含了我所知道的所有Java技术,所以如果您不再包含任何“高级”内容,我将不胜感激。谢谢!
答案 0 :(得分:2)
使用蒙特卡罗方法计算PI的想法是对正方形中的随机点进行采样,并计算落入由该正方形约束的圆的区域内的部分。如果均匀采样足够的点,则该分数将接近圆的面积除以边界的正方形区域:
fraction = PI*r^2/(2r)^2
因此
PI = fraction * 4
。
现在,由于您只采样正坐标,如果我们假设圆位于原点(0,0)
的中心,我们只会在圆的右上四分之一及其边界正方形内采样点,但是方程式保持不变。
如果圆的半径为r,则应采样0和r之间的坐标。
因此你应该改变这个:
double xCoord = Math.random() * 2;
double yCoord = Math.random() * 2;
对此:
double xCoord = Math.random() * r;
double yCoord = Math.random() * r;
此外,条件应为((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= r*r)
。
当然,您可以通过消除r并假设半径为1来简化它。
在这种情况下,条件为((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= 1)
,坐标将在0和1之间进行采样。