pi 円周率πの値を多桁数で算出する
int pi(int *data, int keta);
data (出力)円周率の値が10進4桁ずつ入った整数の配列 keta (入力)小数点以下の桁数の指定
正常に計算できたときに0、エラーのとき-1。
#define LOG10_5 0.699 #define LOG10_239 2.378 int pi(int *data, int keta) { int i; for (i = 0; i < (keta-1)/4+2; i++) data[i] = 0; if (series(data, keta, (int)(keta/(2*LOG10_5)+2), 4, 5, 1) != 0) return -1; if (series(data, keta, (int)(keta/(2*LOG10_239)+2), 1, 239, 0) != 0) return -1; return 0; } int series(int *data, int keta, int maxItem, unsigned bunsi, unsigned bunpo, unsigned plusMinus) { unsigned bunpo2; unsigned *item, *itemDiv; unsigned *imp, *ikp; int *dap; int len; int i, j, k; long x; len = (keta-1)/4+2 +1; if ((item = (unsigned *)calloc(len, sizeof(unsigned))) == NULL) return -1; for (imp = item, i = len; i--; ) *imp++ = 0; if ((itemDiv = (unsigned *)calloc(len, sizeof(unsigned))) == NULL) { free(item); return -1; } *item = bunsi * bunpo * 4; bunpo2 = bunpo * bunpo; for (j = 1; maxItem--; j += 2, plusMinus++) { x = 0; for (i = len, imp = item; i--; ) { x = x * 10000 + *imp; *imp++ = x / bunpo2; x %= bunpo2; } imp = item; ikp = itemDiv; if (j == 1) for (i = len; i--; ) *ikp++ = *imp++; else { x = 0; for (i = len; i--; ) { x = x * 10000 + *imp++; *ikp++ = x / j; x %= j; } } k = 0; dap = data + len; ikp = itemDiv + len; if (plusMinus & 1) { for (i = len; i--; ) { *--dap += *--ikp + k; if (*dap < 10000) k = 0; else { *dap -= 10000; k = 1; } } } else { for (i = len; i--; ) { *--dap -= *--ikp + k; if (*dap >= 0) k = 0; else { *dap += 10000; k = 1; } } } } free(itemDiv); free(item); return 0; }
ここで使う式は、最もよく知られている、J. Machinの式
π/4 = 4 arctan (1/5) - arctan (1/239)
である。彼は1706年にこの公式でπを小数点以下100桁を求めた。
同じ公式で、1949年にはENIACにより2037桁が約70時間で、1958
年にはIBM704により1万桁が約100分で求められている。
皆さんの使うコンピュータでどれぐらいの時間 ?
ちなみに、わたしの使っているPentium 120のDOS/Vマシンでは 1万桁は1分弱で計算できた。ハードウェアの進歩ってすごい !
また、パソコンでの計算記録については、若松登志樹氏が1990年 2月に、富士通FM-TOWNS(メモリ2MB)を用いて、184時間45分を かけ、πを100万桁まで計算した。
arctanをによる古典的な公式にほかに以下のものがある。
ガウスの公式
π/4 = 12 arctan (1/18) + 8 arctan (1/57) - 5 arctan (1/239)
クリンジェンシェルナの公式
π/4 = 8 arctan (1/10) - arctan (1/239) - 4 arctan (1/515)
シュテルマーの公式
π/4 = 6 arctan (1/8) + 2 arctan (1/57) + arctan (1/239)
高野喜久雄の公式
π/4 = 12 arctan (1/49) + 32 arctan (1/57) - 5 arctan (1/239)
+ 12 arctan (1/110443)
柴田昭彦の公式
π/4 = 17 arctan (1/22) + 3 arctan (1/172) - 2 arctan (1/682)
- 7 arctan (1/5357)
シュテルマーの公式に8の割り算を工夫すれば高速化期待できるし、 高野の公式を利用して並列処理をすれば良い成績が期待できよう。
arctanを使った公式でπを計算すると、桁数を2倍にするのに計算時間 は4倍の増加になるが、以下の方法では2.1〜2.2倍で済む。
ガウス・ルジャンドルの公式
A = 1、B = (1/2)1/2、T = 1/4、X = 1
として、AとBの差が必要とする精度より大きい間、次の計算を繰り返し
実行する。
Y = A、A = (A + B)/2、B = (B * Y)1/2、
T = T - X * (Y-A)2、X = 2 * X
すると、πの値は(A + B)2/(4 * T) となる。ただし、A、B、T、
Yの各値は、求めようとする精度以上で計算しておく必要がある。