2020.12.22

数学

格子座標から円周率πを計算

円周率πを計算で求める方法を紹介します。

ここでは、単位円を外接する正方形を格子状に区切り、格子全体の座標数と、の中に入っている座標の比率を利用して円周率πを求める方法を紹介します。

単位円の中心座標を(0,0)とすると、外接する正方形の左上の座標は(-1,1)、右下の座標は(1,-1)です。

単位円を外接する正方形
単位円を外接する正方形

この正方形の1辺の長さは2で、面積は4(=2x2)です。単位円面積π(=1x1xπ)です。

よって、以下の比が成り立ちます。

外接正方形面積 : 格子全体の座標数 = 単位円面積 : 内の格子座標

これを単位円面積を計算する式に変形すると、

単位円面積=外接正方形面積×(内の格子座標数÷格子全体の座標数)

となります。

この式は、格子の数が多ければ大きいほど円周率πに近づきます。

下図の例は、格子の座標数が全部で81で、円周率πの計算結果は2.42となりました。格子の座標数が少ないので精度が悪いです。円周率3.14には程遠いです。

格子の座標数から円周率πを計算

それでは、格子を使った円周率πを求めるプログラムを見ていきましょう。

Javaソースコード

以下は、Javaソースコードです。x軸y軸を20000分割して計算しています。

GridPI.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
public class GridPI {
	public static void main( String[] args ) {
		// 変数の宣言
		int    cellnum;
		int    x, y;
		double in_num;
		double left, right;
		double top, bottom;
		double celllen;
		double cellx, celly;
		double l2;

		// 単位円に外接する正方形の左上と右下の座標を代入
		// 左上の座標
		left = -1.0;
		top = 1.0;

		// 右下の座標
		right = 1.0;
		bottom = -1.0;

		// 1辺の格子の数
		cellnum = 20000;

		// セルの幅を計算(x軸だけで計算)
		celllen = ( right - left ) /  (double)( cellnum - 1 );

		// 円周率πの計算のメイン
		// 円内の座標の個数を初期化
		in_num = 0.0;

		// 格子のy座標の初期値
		celly = top;
		for ( y = 0; y < cellnum; y++ ) {
			// 格子のx座標の初期値
			cellx = left;
			for ( x = 0; x < cellnum; x++ ) {
				// 単位円の中心座標(0,0)と
				//セルの直線距離の2乗を計算
				l2 = cellx * cellx + celly * celly;

				// 単位円の中かを判定
				if ( 1.0 >= l2 ) {
					// 単位円の中と判定
					// 単位円の線上も中と判定
					++ in_num;
				}
				// 格子のx座標にセルの幅を足す
				cellx += celllen;
			}
			// 格子のy座標からセルの幅を引く
			celly -= celllen;
		}

		// 外接正方形の面積を計算(計算結果は4.0)
		double sq_area = ( right - left ) * ( top - bottom ); 		

		// 格子全体の座標数
		double all_num =  (double)cellnum *  (double)cellnum;

		// 円周率πを計算
		double pi = sq_area * in_num / all_num;

		// 結果を出力
		System.out.println( pi );
	}
}

コンパイル ソースコードが「ANSI」の場合

C:\talavax\javasample>javac -encoding sjis GridPI.java

コンパイル ソースコードが「UTF-8」の場合

C:\talavax\javasample>javac GridPI.java

実行

C:\talavax\javasample>java GridPI

出力結果

3.14127716

実際の円周率πは、

3.141592653589793238462・・・

です。分割数20000でも小数点以下第3桁までしか一致しません。

この方法は、精度は悪く実用的ではないです。

Javaソースコードの解説

001
public class GridPI {

クラス名を、GridPIとしています。

002
	public static void main( String[] args ) {

このmainメソッドからプログラムを実行します。

003
004
005
006
007
008
009
010
011
		// 変数の宣言
		int    cellnum;
		int    x, y;
		double in_num;
		double left, right;
		double top, bottom;
		double celllen;
		double cellx, celly;
		double l2;

このプログラムで使う変数を宣言しています。

013
014
015
016
		// 単位円に外接する正方形の左上と右下の座標を代入
		// 左上の座標
		left = -1.0;
		top = 1.0;

単位円を外接する正方形の左上の座標を代入しています。

018
019
020
		// 右下の座標
		right = 1.0;
		bottom = -1.0;

単位円を外接する正方形の右下の座標を代入しています。

022
023
		// 1辺の格子の数
		cellnum = 20000;

x軸y軸の格子の数を格納する変数cellnumに20000を代入しています。

025
026
		// セルの幅を計算(x軸だけで計算)
		celllen = ( right - left ) /  (double)( cellnum - 1 );

正方形x軸方向の長さを格子の数から1を引いた値( cellnum - 1 )で割って格子の間隔を計算し、変数celllenに代入しています。

028
029
030
		// 円周率πの計算のメイン
		// 円内の座標の個数を初期化
		in_num = 0.0;

ここから円周率πの計算です。

の内側の個数の初期値に0を代入しています。

032
033
034
035
036
037
		// 格子のy座標の初期値
		celly = top;
		for ( y = 0; y < cellnum; y++ ) {
			// 格子のx座標の初期値
			cellx = left;
			for ( x = 0; x < cellnum; x++ ) {

for文正方形に含まれる全ての格子座標(cellx,celly)を求めています。

038
039
040
041
042
043
044
045
046
047
				// 単位円の中心座標(0,0)と
				//セルの直線距離の2乗を計算
				l2 = cellx * cellx + celly * celly;

				// 単位円の中かを判定
				if ( 1.0 >= l2 ) {
					// 単位円の中と判定
					// 単位円の線上も中と判定
					++ in_num;
				}

単位円の中心座標(0,0)と(cellx,celly)の直線距離2乗を計算した値を変数l2に代入し、その値が単位円半径2乗(1.0=1.0x1.0)以下の場合にの中に入っていると判定し、変数in_numに1を足しています。

048
049
050
051
052
				// 格子のx座標にセルの幅を足す
				cellx += celllen;
			}
			// 格子のy座標からセルの幅を引く
			celly -= celllen;

変数xのfor文でcellxにcelllenを足しています。変数yのfor文でcellyからcelllenを引いています。

これで左上から右下の順番で格子座標(cellx,celly)を求めています。

055
056
		// 外接正方形の面積を計算(計算結果は4.0)
		double sq_area = ( right - left ) * ( top - bottom ); 		

単位円に外接する正方形面積を計算した結果を変数sq_areaに代入しています。

058
059
		// 格子全体の座標数
		double all_num =  (double)cellnum *  (double)cellnum;

格子全ての座標数を計算した結果を変数all_numに代入しています。

061
062
		// 円周率πを計算
		double pi = sq_area * in_num / all_num;

円周率πを計算して、変数piに代入しています。

064
065
		// 結果を出力
		System.out.println( pi );

円周率πコンソール出力しています。、

以上です。

関連コンテンツ

数学に関係するJavaのメソッドやソースコードなどを紹介しています。

2022.10.25

変数やクラスに格納されている値をコンソール出力する方法は?

2020.03.23

円周率、πってどうゆう意味?

2020.03.23

単位円の意味をくわしく解説しています。

2020.03.23

処理を繰り返すために使用するfor文について解説しています。

2020.03.23

繰り返し処理の作り方を解説しています。

2016.03.02

条件式を判断して処理を分岐する方法を詳しく説明しています。

2023.03.20

円の面積を計算する公式を使って、円の面積を計算する方法を説明しています。記事でくわしく説明しています。興味のある方は、ご覧ください。

2020.03.23

Javaの学習に役立つソースコードを多数紹介しています。是非、ご覧ください。

2022.09.10

Javaを使った簡単な応用プログラム(生年月日から年齢を計算プログラムなど)を紹介しています。

2022.07.07

画像フォーマット形式・色・大きさ・傾きなどの変更、特定の図形(文字・記号など)を見つけたり、取り出したりする画像処理について詳しく解説。

2015.11.29

日本で使われてきた伝統文様「和柄」について解説しています。

2022.07.27

プログラミング、ITに関する用語をまとめています。

2022.10.17

プログラムの最初に実行されるメソッドは?

2022.12.13

プログラミングで使う変数って何?

2020.03.23

Javaのプログラムを書いてみませんか?プログラムの書き方をくわしく説明しています。

2020.03.23

「Javaソースコード」から実行可能な「オブジェクトコード」に変換する方法をくわしく説明しています。

2020.03.23

正方形の面積、周の長さ、関連する記事を紹介しています。興味のある方は、ご覧ください。

2020.03.23

平面上の位置を表す座標系の1つXY座標系について詳しく解説。

2020.03.23

面積について詳しく解説しています。いろいろな図形の面積計算のリンク付き。

2019.10.7

プログラミング言語とは?種類や特徴について説明しています。

2022.08.03

Javaプログラムの構成について解説しています。詳しくは、こちらをご覧ください。

2020.03.23

for文で変数名iがよく使われる理由について説明しています。興味のある方は是非。

2022.08.29

値の2乗を計算するメソッドの作り方を解説しています。

2020.03.23

2つの座標(x1,y1)と(x2,y2)の直線距離を求める計算式は?

2020.03.23

円の直径と半径について図を使って詳しく解説しています。

2020.03.23

広告