AHA!caffiend:他の(より長い)答え(具体的には「重複する剰余」)に対するあなたのコメントは、O(n)である非常に単純な解決策につながります。ここで、n =非反復+反復部分の長さの合計であり、整数のみが必要です。 0から10*yまでの数値を使用した数学。ここで、yは分母です。
有理数x/yの小数点の右側のn番目の桁を取得するJavascript関数は次のとおりです。
function digit(x,y,n)
{
if (n == 0)
return Math.floor(x/y)%10;
return digit(10*(x%y),y,n-1);
}
これは反復ではなく再帰的であり、サイクルを検出するのに十分なほどスマートではありません(1/3の10000桁目は明らかに3ですが、これは10000回目の反復に達するまで継続します)が、少なくともスタックがなくなるまで機能しますメモリー。
基本的に、これは2つの事実のために機能します。
- x /yのn番目の桁は10x/yの(n-1)番目の桁です(例:1/7の6番目の桁は10/7の5番目の桁は100/7の4番目の桁ですなど)
- x / yのn番目の桁は(x%y)/ yのn番目の桁です(例:10/7の5番目の桁は3/7の5番目の桁でもあります)
これを反復ルーチンになるように調整し、フロイドの循環検出アルゴリズム(Martin Gardnerのコラムから「rho」メソッドとして学習した)と組み合わせて、このアプローチを短縮するものを取得できます。
このアプローチでソリューションを計算するjavascript関数は次のとおりです。
function digit(x,y,n,returnstruct)
{
function kernel(x,y) { return 10*(x%y); }
var period = 0;
var x1 = x;
var x2 = x;
var i = 0;
while (n > 0)
{
n--;
i++;
x1 = kernel(x1,y); // iterate once
x2 = kernel(x2,y);
x2 = kernel(x2,y); // iterate twice
// have both 1x and 2x iterations reached the same state?
if (x1 == x2)
{
period = i;
n = n % period;
i = 0;
// start again in case the nonrepeating part gave us a
// multiple of the period rather than the period itself
}
}
var answer=Math.floor(x1/y);
if (returnstruct)
return {period: period, digit: answer,
toString: function()
{
return 'period='+this.period+',digit='+this.digit;
}};
else
return answer;
}
そして、1/700のn番目の桁を実行する例:
js>1/700
0.0014285714285714286
js>n=10000000
10000000
js>rs=digit(1,700,n,true)
period=6,digit=4
js>n%6
4
js>rs=digit(1,700,4,true)
period=0,digit=4
33/59についても同じです。
js>33/59
0.559322033898305
js>rs=digit(33,59,3,true)
period=0,digit=9
js>rs=digit(33,59,61,true)
period=58,digit=9
js>rs=digit(33,59,61+58,true)
period=58,digit=9
そして122222/990000(長い非反復部分):
js>122222/990000
0.12345656565656565
js>digit(122222,990000,5,true)
period=0,digit=5
js>digit(122222,990000,7,true)
period=6,digit=5
js>digit(122222,990000,9,true)
period=2,digit=5
js>digit(122222,990000,9999,true)
period=2,digit=5
js>digit(122222,990000,10000,true)
period=2,digit=6
一連の数字を検出する別の関数は次のとおりです。
// find digits n1 through n2 of x/y
function digits(x,y,n1,n2,returnstruct)
{
function kernel(x,y) { return 10*(x%y); }
var period = 0;
var x1 = x;
var x2 = x;
var i = 0;
var answer='';
while (n2 >= 0)
{
// time to print out digits?
if (n1 <= 0)
answer = answer + Math.floor(x1/y);
n1--,n2--;
i++;
x1 = kernel(x1,y); // iterate once
x2 = kernel(x2,y);
x2 = kernel(x2,y); // iterate twice
// have both 1x and 2x iterations reached the same state?
if (x1 == x2)
{
period = i;
if (n1 > period)
{
var jumpahead = n1 - (n1 % period);
n1 -= jumpahead, n2 -= jumpahead;
}
i = 0;
// start again in case the nonrepeating part gave us a
// multiple of the period rather than the period itself
}
}
if (returnstruct)
return {period: period, digits: answer,
toString: function()
{
return 'period='+this.period+',digits='+this.digits;
}};
else
return answer;
}
私はあなたの答えの結果を含めました(Javascript#がオーバーフローしなかったと仮定して):
js>digit(1,7,1,7,true)
period=6,digits=1428571
js>digit(1,7,601,607,true)
period=6,digits=1428571
js>1/7
0.14285714285714285
js>digit(2124679,214748367,214748300,214748400,true)
period=1759780,digits=20513882650385881630475914166090026658968726872786883636698387559799232373208220950057329190307649696
js>digit(122222,990000,100,110,true)
period=2,digits=65656565656