モンテカルロ法 [Java アプレット ] [Java アプリケーション ] 1. はじめに 一辺の長さが 2 の正方形とそれに内接する半径 1 の円が紙に書かれています この紙の上からたくさんのゴマをばらまきます 正方形の中に入ったゴマの数と そのうちで円の中に入ったゴマの数も数えます さあ このゴマの数からどうやって円周率 π を求めるのでしょうか <シミュレーションの考え方 > 一辺の長さ2の正方形の面積は4で それに内接する半径 1の円の面積をSとします 更に 正方形の中に入ったゴマの数をN 個 円の中に入ったゴマの数をn 個とします ( 一辺の長さ2の正方形の面積 ):( それに内接する半径 1の円の面積 ) =( 正方形の中に入ったゴマの数 ):( 円の中に入ったゴマの数 ) が成り立つので 4:S=N:n となります よって S=4n/N となり nとnが分かれば Sが求まります S= 半径 半径 π=1 1 π となるので S=π となり 求める円周率 πは 先ほど求め た面積 Sになります このように 確率を利用して問題を解決する方法を モンテカルロ法 と言います シミュレーションソフト ゴマをまいて円周率 πを求める を使って 円周率 πの近似値が求まる 様子を観察してみてください 2.Java アプレット (1) Java プログラムリスト モンテカルロ法によるπの近似 ( ゴマをまいて 円周率 πが求まる!!) Copyright ( C) K.Niwa 2001.11. 6 (Javaアプレット) import java.applet.applet; import java.awt.*; import java.awt.event.*; -144-
import java.lang.math; public class Montecal2 extends Applet{ Button[] mybtn; ボタン型として宣言する Panel mypanel; パネル型として宣言する int flag; 変数宣言 double x; int N; ゴマの個数 int count; ループカウンター *****public void init() init メソット ( void は値を返さないメソッドの意 )************************ public void init(){ setbackground( Color.lightGray ); mybtn=new Button[ 4 ]; 背景色をグレーにする ボタンの実体化 mybtn[ 0 ] =new Button (" 初期化 "); mybtn[ 1 ] =new Button (" 自動 500 個 "); mybtn[ 2 ] =new Button (" 自動 5000 個 "); mybtn[ 3 ] =new Button (" 自動 50000 個 "); mypanel=new Panel (); パネルの実態化 mypanel.setlayout( new GridLayout( 1,4 )); ハ ネルをク リット レイアウトにする for ( count=0;count < =3;count++ ){ パネルにボタンを貼り付ける mypanel.add( mybtn[ count ]); setlayout( new BorderLayout ()); 全体をボーダーレイアウトにする add ("South",myPanel); パネルを南に貼り付ける 初期化ボタンを押したときのイベント処理 mybtn[ 0 ].addactionlistener( new ActionListener(){ flag=0; ボタン識別子 ); 自動 500 個ボタンを押したときのイベント処理 mybtn[ 1 ].addactionlistener( new ActionListener(){ flag=1; ボタン識別子 N=500; ); 自動 5000 個ボタンを押したときのイベント処理 mybtn[ 2 ].addactionlistener( new ActionListener(){ flag=2; ボタン識別子 N=5000; ); 自動 50000 個ボタンを押したときのイベント処理 mybtn[ 3 ].addactionlistener( new ActionListener(){ flag=3; ボタン識別子 N=50000; ); public void init() -145-
*****paint メソット *************************************************************************** public void paint( Graphics g){ if ( flag==0){ g.drawstring ("Copyright( C) K.Niwa 2001.11",10,20 ); 作者名 else if ( flag==1 flag==2 flag==3){ double x,y,pai,t; 変数宣言 int i,sum=0,px,py; 変数宣言と変数初期化 for ( i=1;i < =N;i++ ){ for ( t=0;t< 1000;t++ ){ 時間稼ぎ x=math.random (); y=math.random (); if ( x*x+y*y< 1 ){ 円内に入ったら g.drawline( px,py,px,py ); 点を打つ sum++; else if ( x*x+y*y> 1){ g.setcolor( Color.white ); g.drawline( px,py,px,py ); 点を打つ Font f=new Font(( g.getfont ()).getname(),font.bold,20); g.setfont() f ; g.clearrect( 0,305,300,55 ); g.setcolor( Color.black ); g.drawstring( sum+" / "+i+" 個 ",80,325); g.drawstring (π= " "+pai,170,280); (2) HTML リスト < HTML > < HEAD> <!------------------------------------------------------------------------------------------------------------------------------------- ゴマをまいて円周率 πを求める ( モンテカルロ法によるπの近似 ) Copyright ( C) K.Niwa 2001.11. 6 --------------------------------------------------------------------------------------------------------------------------------------> < /HEAD> < BODY > < CENTER< > B > ゴマをまいて円周率 πを求める!! < /B> < BR> ( モンテカルロ法によるπの近似 ) < BR>< BR> < APPLET CODE="Montecal2.class" WIDTH="350" HEIGHT="360" >< /APPLET> < BR>< BR> ゴマを 50,000 個まいて πの近似値を求めています... -146-
< /CENTER> < /BODY> < /HTML> 3.Java アプリケーション プログラムリスト Fモンテカルロ法によるπの近似 ( ゴマをまいて 円周率 πが求まる!!) Copyright ( C) K.Niwa 2002.08.24 (Javaアプリケーション) import java.awt.*; import java.awt.event.*; import java.lang.math; public class FMontecal2 extends Frame { Frame クラスを継承する Button[] mybtn; Panel mypanel; ボタン型として宣言する パネル型として宣言する int flag; 変数宣言 double x; int N; int count; ゴマの個数 ループカウンター ***** フレームとイベントの定義 ************************************************************ public FMontecal2(){ setbackground( Color.lightGray ); 背景色を黒にする setsize( 300+20,360 ); フレームの大きさ addwindowlistener( new WindowAdapter (){ 閉じるボタンのイベント public void windowclosing( WindowEvent e){ System.exit( 0 ); ); mybtn=new Button[ 4 ]; ボタンの実体化 mybtn[ 0 ] =new Button (" 初期化 "); mybtn[ 1 ] =new Button (" 自動 500 個 "); mybtn[ 2 ] =new Button (" 自動 5000 個 "); mybtn[ 3 ] =new Button (" 自動 50000 個 "); mypanel=new Panel (); パネルの実体化 mypanel.setlayout( new GridLayout( 1,4 )); ハ ネルをク リット レイアウトにする for ( count=0;count < =3;count++ ){ mypanel.add( mybtn[ count ]); パネルにボタンを貼り付ける setlayout( new BorderLayout ()); 全体をボーダーレイアウトにする add ("South",myPanel); パネルを南に貼り付ける 初期化ボタンを押したときのイベント処理 mybtn[ 0 ].addactionlistener( new ActionListener(){ flag=0; ボタンの識別子 ); -147-
自動 500 個ボタンを押したときのイベント処理 mybtn[ 1 ].addactionlistener( new ActionListener(){ flag=1; ボタンの識別子 N=500; ); 自動 5000 個ボタンを押したときのイベント処理 mybtn[ 2 ].addactionlistener( new ActionListener(){ flag=2; ボタンの識別子 N=5000; ); 自動 50000 個ボタンを押したときのイベント処理 mybtn[ 3 ].addactionlistener( new ActionListener(){ flag=3; ボタンの識別子 N=50000; ); public FMontecal2() *****paint メソット *************************************************************************** public void paint( Graphics g){ if ( flag==0){ g.drawstring ("Copyright( C) K.Niwa 2001.11",10,20 ); 作者名 else if ( flag==1 flag==2 flag==3){ double x,y,pai,t; 変数宣言 int i,sum=0,px,py; 変数宣言と変数初期化 for ( i=1;i < =N;i++ ){ for ( t=0;t< 1000;t++ ){ 時間稼ぎ x=math.random (); y=math.random (); if ( x*x+y*y< 1 ){ 円内に入ったら g.drawline( px,py,px,py ); 点を打つ sum++; else if ( x*x+y*y> 1){ g.setcolor( Color.white ); g.drawline( px,py,px,py ); 点を打つ Font f=new Font(( g.getfont ()).getname(),font.bold,20); g.setfont() f ; -148-
g.clearrect( 0,305,300,55 ); g.setcolor( Color.black ); g.drawstring( sum+" / "+i+" 個 ",80,325); g.drawstring (π= " "+pai,170,280); public void paint( Graphics g) /****** public static void main メソット *********************************************************/ public static void main( String[] args){ Frame w=new FMontecal2 (); w.show (); public static void main( String[] args) public class FMontecal2 extends Frame -149-