2020/12/22 公開
・格子座標から円周率πを計算
ここでは、単位円を外接する正方形を格子状に区切り、格子全体の座標数と、円の中に入っている座標の比率を利用して円周率πを求める方法を紹介します。
単位円の中心座標を(0,0)とすると、外接する正方形の左上の座標は(-1,1)、右下の座標は(1,-1)です。

x軸とy軸をそれぞれ等分割し格子を作成します。下の例は、xとyを8分割し、1列に9個の座標を配置したものです。

この正方形の1辺の長さは2で、面積は4(=2x2)です。単位円の面積はπ(=1x1xπ)です。
よって、以下の比が成り立ちます。
外接正方形の面積 : 格子全体の座標数 = 単位円の面積 : 円内の格子座標数
単位円の面積=外接正方形の面積×(円内の格子座標数÷格子全体の座標数)
となります。
この式は、格子の数が多ければ大きいほど円周率πに近づきます。
下図の例は、格子の座標数が全部で81で、円周率πの計算結果は2.42となりました。格子の座標数が少ないので精度が悪いです。円周率3.14には程遠いです。

それでは、格子を使った円周率πを求めるプログラムを見ていきましょう。
以下は、Javaソースコードです。x軸とy軸を20000分割して計算しています。
GridPI.java ← クリックしてダウンロードページに移動
001: public class GridPI { 002: public static void main( String[] args ) { 003: // 変数の宣言 004: int cellnum; 005: int x, y; 006: double in_num; 007: double left, right; 008: double top, bottom; 009: double celllen; 010: double cellx, celly; 011: double l2; 012: 013: // 単位円に外接する正方形の左上と右下の座標を代入 014: // 左上の座標 015: left = -1.0; 016: top = 1.0; 017: 018: // 右下の座標 019: right = 1.0; 020: bottom = -1.0; 021: 022: // 1辺の格子の数 023: cellnum = 20000; 024: 025: // セルの幅を計算(x軸だけで計算) 026: celllen = ( right - left ) / (double)( cellnum - 1 ); 027: 028: // 円周率πの計算のメイン 029: // 円内の座標の個数を初期化 030: in_num = 0.0; 031: 032: // 格子のy座標の初期値 033: celly = top; 034: for ( y = 0; y < cellnum; y++ ) { 035: // 格子のx座標の初期値 036: cellx = left; 037: for ( x = 0; x < cellnum; x++ ) { 038: // 単位円の中心座標(0,0)と 039: //セルの直線距離の2乗を計算 040: l2 = cellx * cellx + celly * celly; 041: 042: // 単位円の中かを判定 043: if ( 1.0 >= l2 ) { 044: // 単位円の中と判定 045: // 単位円の線上も中と判定 046: ++ in_num; 047: } 048: // 格子のx座標にセルの幅を足す 049: cellx += celllen; 050: } 051: // 格子のy座標からセルの幅を引く 052: celly -= celllen; 053: } 054: 055: // 外接正方形の面積を計算(計算結果は4.0) 056: double sq_area = ( right - left ) * ( top - bottom ); 057: 058: // 格子全体の座標数 059: double all_num = (double)cellnum * (double)cellnum; 060: 061: // 円周率πを計算 062: double pi = sq_area * in_num / all_num; 063: 064: // 結果を出力 065: System.out.println( pi ); 066: } 067: }
GridPIを実行
C:\talavax\javasample>java GridPI
GridPI.javaの出力結果
3.14127716
3.141592653589793238462・・・
です。分割数20000でも小数点以下第3桁までしか一致しません。この方法は、精度は悪く実用的ではないです。
001: public class GridPI {
クラス名を、GridPIとしています。
002: public static void main( String[] args ) {
このmainメソッドからプログラムを実行します。
003: // 変数の宣言 004: int cellnum; 005: int x, y; 006: double in_num; 007: double left, right; 008: double top, bottom; 009: double celllen; 010: double cellx, celly; 011: double l2;
このプログラムで使う変数を宣言しています。
013: // 単位円に外接する正方形の左上と右下の座標を代入 014: // 左上の座標 015: left = -1.0; 016: top = 1.0;
018: // 右下の座標 019: right = 1.0; 020: bottom = -1.0;
022: // 1辺の格子の数 023: cellnum = 20000;
x軸とy軸の格子の数を格納する変数cellnumに20000を代入しています。
025: // セルの幅を計算(x軸だけで計算) 026: celllen = ( right - left ) / (double)( cellnum - 1 );
正方形のx軸方向の長さを格子の数から1を引いた値( cellnum - 1 )で割って格子の間隔を計算し、変数celllenに代入しています。
028: // 円周率πの計算のメイン 029: // 円内の座標の個数を初期化 030: in_num = 0.0;
ここから円周率πの計算です。円の内側の個数の初期値に0を代入しています。
032: // 格子のy座標の初期値 033: celly = top; 034: for ( y = 0; y < cellnum; y++ ) { 035: // 格子のx座標の初期値 036: cellx = left; 037: for ( x = 0; x < cellnum; x++ ) {
for文で正方形に含まれる全ての格子座標(cellx,celly)を求めています。
038: // 単位円の中心座標(0,0)と 039: //セルの直線距離の2乗を計算 040: l2 = cellx * cellx + celly * celly; 041: 042: // 単位円の中かを判定 043: if ( 1.0 >= l2 ) { 044: // 単位円の中と判定 045: // 単位円の線上も中と判定 046: ++ in_num; 047: }
単位円の中心座標(0,0)と(cellx,celly)の直線距離の2乗を計算した値を変数l2に代入し、その値が単位円の半径の2乗(1.0=1.0x1.0)以下の場合に円の中に入っていると判定し、変数in_numに1を足しています。
048: // 格子のx座標にセルの幅を足す 049: cellx += celllen; 050: } 051: // 格子のy座標からセルの幅を引く 052: celly -= celllen;
変数xのfor文でcellxにcelllenを足しています。変数yのfor文でcellyからcelllenを引いています。これで左上から右下の順番で格子座標(cellx,celly)を求めています。
055: // 外接正方形の面積を計算(計算結果は4.0) 056: 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;
064: // 結果を出力 065: System.out.println( pi );
以上です。
■関連コンテンツ
点が円内かを判定 | 点が円の中か?外か? |
値のコンソール表示 | print()、println()とは? |
![]() |
円周率π(パイ)π(パイ)の意味と、Math.PIの使い方について解説 |
![]() |
単位円単位円は半径が1の円のことです。単位円と三角関数(sinθ、cosθ)の関係についても解説しています。 |
![]() |
for文繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。 |
![]() |
if文条件による処理の分岐に使用するif文について解説 |
![]() |
円の面積計算半径を与えて円の面積を計算するプログラムを解説します。円の面積は、半径×半径×円周率でで計算できます。 |
■新着情報
2022.07.07 | 外部プログラムの実行 | exeファイル実行 |
2022.07.06 | 完全数 | 6=1+2+3 |
■広告
