円周率に近似できる分数
締め切りが 201701/31 10:00 AM なので,その 1 分後に投稿されるように予約
設問
分母、分子ともに整数の分数を使って円周率に近似することを考えます。
小数第 n 位までが円周率と一致するもののうち、分母が最小のものをπ(n)とします。
例えば、n = 1 のとき、π(1) = 19/6 = 3.166…、
n = 2 のとき、π(2) = 22/7 = 3.1428…、
n = 3 のとき、π(3) = 245/78 = 3.14102…
となります。
標準入力から n が与えられたとき、π(n) の分母を求め、標準出力に出力してください。
なお、nは11以下の正の整数とします。
参考)小数点以下11桁までの円周率は以下の通りです。
3.14159265358
【入出力サンプル】
標準入力
2
標準出力
7
=====================================
素直に書けばよいが,R ならではの落とし穴があった。
repeat ループは本来は for (denominator in 1:pow10n) とするのであるが,R の for ループは変域を前もって配列として確保するので,n = 1e11 の場合のようなサイズ(1:1e11)のサイズを取ろうとするとメモリー管理上不都合が生じる。そのため,本来は遅い(?)repeat ループにした。
また,評価システムの実行時間制限(1 秒以内)に沿うために不本意ながら,denominator の変域を制限した。
もちろん,Java などを用いればそんな小細工は不要である。
π = function(n) {
pow10n = 10^n
aproxPI = floor(pi* pow10n)
denominator = ifelse(n < 10, 0, 165000)
repeat {
denominator = denominator+1
if (denominator > pow10n) break
if (any(floor(((floor(denominator*pi)+(-1:1))/denominator)*pow10n) == aproxPI)) break
}
cat(denominator)
}
π(1) # 6
π(2) # 7
π(3) # 78
π(4) # 106
π(5) # 113
π(6) # 113
π(7) # 27678
π(8) # 32763
π(9) # 33102
π(10) # 165849
π(11) # 265381
=====================================
Java の場合
static int PI(int n) {
double aproxPI, x, PI;
double [] y = {-2.0, -1.0, 0.0, 1.0, 2.0};
double pow10 = Math.pow(10, n);
int denominator;
int i;
boolean ok;
aproxPI = Math.floor(Math.PI*pow10)/pow10;
for (denominator = 1; denominator
ok = false;
for (i = 0; i < 5; i++) {
x = y[i]+Math.floor(denominator*Math.PI);
PI = Math.floor(x/denominator*pow10)/pow10;
if (PI == aproxPI) {
ok = true;
break;
}
}
if (ok) {
break;
}
}
return denominator;
}