2016-08-13 3 views
3

그래프에서 x, y 좌표를 나타내는 무작위로 생성 된 부동 소수점 숫자를 기반으로 pi을 계산하는 프로그램을 작성 중입니다. 각 x, y 좌표는 2의 거듭 제곱으로 올림되고 두 개의 개별 배열에 저장됩니다. 좌표는 0,1 간격의 그래프에 균일하게 분포됩니다.Java에서 무작위로 생성 된 데이터를 사용하여 pi의 몬테카를로 계산

프로그램에서 x, y 좌표를 더하고 1보다 작 으면 점은 아래 다이어그램과 같이 직경 1의 ​​원 안에 위치합니다.

enter image description here

I는 다음 수식을 사용

π ≈ 4 /N

승 PI를 해결한다. 여기서, w은 원안에있는 점의 수이고 n은 배열 내의 x 또는 y 좌표의 수입니다.

n을 10,000,000 (배열의 크기)까지 설정하면 십진수 15-16 자의 가장 정확한 pi 계산이 생성됩니다. 그러나 4GB RAM을 실행 설정에 할당하고 n을 100,000,000으로 설정하면 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

하지 대답, 그래서 나는 그것을 놓을 게요 논평. 1/4 원의 면적을'base * avg_height'로 산정하여보다 낮은 분산 추정치를 얻을 수 있습니다. 'x ** 2 + y ** 2 = 1'은 원의 둘레를 정의하므로'y = sqrt (1 - x ** 2)'입니다. 'x' 값을 균등하게 생성하고, 변환하여'y'를 찾고,'y'의 평균 높이를 계산하십시오. 'x '의 범위는 (0,1)이기 때문에 밑이 1이므로 결과적으로 1/4 원의 면적은'avg_height'가됩니다. Pi를 계산하려면 4를 곱합니다. – pjs

+0

그건 그렇고, 십진법의 수는 쓸모없는 조치입니다. 당신은 Z = 4 * sqrt ((w/n) * (1 - w/n)/n)'이 될 추정 오차의 오차를 계산해야합니다. 여기서 Z는 표준 정규 분포와 신뢰 수준. Z에 대한 일반적인 선택은 1.96입니다. – pjs

+0

알다시피, 나는이 정보를 주셔서 감사합니다. – girthquake

답변

3

문제는 여기에 있습니다 :

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(); 
    } 
} 

출력 :이 작업 예제 코드처럼

:

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

float 정밀도 int 또는 double로 변경, 충분하지 않습니다 :

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이 도움이되기를 바랍니다. –

+0

대단히 감사합니다. 많은 설명과 개선에 감사드립니다.내가 제안한 변경 사항을 적용하기 전에 pi를 가장 정확하게 계산하려면 n을 최대 21,366,805로 설정해야했습니다. 이제는 4GB 이상의 RAM을 사용하여 10 억 개로 설정할 수 있습니다. – girthquake