2016-08-13 105 views
3

我正在研究一個程序,該程序基於隨機生成的表示座標的x,y座標的浮點數來計算pi。每個x,y座標由2的冪次提升並存儲在兩個獨立的數組中。座標在0,1間隔的圖上均勻分佈。使用Java中隨機生成的數據的pi的蒙特卡羅計算

該程序添加x,y座標,如果它們小於1,則這些點位於直徑爲1的圓內,如下圖所示。

enter image description here

然後所用式I,

π≈4瓦特/Ñ

制定出PI。其中,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(); 
    } 
} 
+1

不是一個答案,所以我把它當成一個評論。通過估算四分之一圓的面積爲「base * avg_height」,您可以獲得較低的方差估計值。 'x ** 2 + y ** 2 = 1'定義了圓的周長,所以'y = sqrt(1 - x ** 2)'。統一生成'x'值,轉換爲'y'並計算'y'的平均高度。由於'x'的範圍是(0,1),因此基數爲1,因此四分之一圓的面積爲「avg_height」。乘以4來估計Pi。 – pjs

+0

順便說一下,小數位數是無用的量度。你應該計算估計值的誤差範圍,它是'Z * 4 * sqrt((w/n)*(1-w/n)/ n)',其中Z是標準正態分佈和期望值置信度。 Z的常見選擇是1.96。 – pjs

+0

我明白了,我會放棄這一點,感謝您的信息。 – girthquake

回答

3

的問題是在這裏:

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 
+0

@rks我希望這有助於。 – 2016-08-13 04:32:52

+0

非常感謝您的支持,非常感謝您的解釋和改進。在我提出修改之前,我設法將n最大設置爲21,366,805,以便最準確地計算pi。如果現在我有超過4GB的內存專用,我可以嘗試設置n十億。 – girthquake