繰り返し小数を見つけるための効率的な方法は何ですか


24

私は2つの整数の循環小数部分を見つけるためにJavaで効率的なアルゴリズムを見つけようとしていますaし、bどこをa/b

例えば。5/7 = 0.714258 714258 ....

私は現在、長い除算方法のみを知っています。


2
したがって、a = 5とb = 7があり、浮動小数点でa / bを簡単に計算できますが、知っておきたいのは、小数点以下6桁で繰り返すことです。
スパー

回答:


10

ここには2つの一般的なアプローチがあると思います。基本的に「ブルートフォース」で最も長い繰り返し文字列を探すか、それを数論の問題として解決することができます。

私がこの問題に出くわしてから長い時間が経ちましたが、特別なケース(1 / n)はProject Eulerの問題#26であるため、その特定の名前の効率的な解決策を検索することでより多くの情報を見つけることができるかもしれません。1回の検索でEli BenderskyのWebサイトに移動し、そこで彼が解決策を説明します。MathworldのDecimal Expansionsページの理論の一部を次に示します

非正規分数m/nは周期的であり、最大で 数字の長さであるからlambda(n)独立した周期を持ちます。もしは、その後の期間、10と互いに素であるのの除数であると最大であり数字、トーティエント関数です。それは、10(mod )の乗法次数であることがわかります(Glaisher 1878、Lehmer 1941)。有理数の10進数展開の繰り返し部分の桁数は、その分母の乗数の順序から直接見つけることもできます。mn-1nlambda(n)m/nphi(n)phi(n)philambda(n)n

私の数論は現時点では少し錆びているので、私ができる最善のことはその方向にあなたを向けることです。


8

みましょうn < d、あなたはの繰り返し部分を理解しようとしていますn/d。ましょうp繰り返し部分の桁数:then n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...)。括弧で囲まれた部分は、に等しい幾何級数1/(10^p - 1)です。

だからn / d = R / (10^p - 1)。取得するように再配置しますR = n * (10^p - 1) / d。Rを見つけるにはp、1から無限にループし、がd均等に分割されるとすぐに停止しn * (10^p - 1)ます。

Pythonでの実装は次のとおりです。

def f(n, d):
    x = n * 9
    z = x
    k = 1
    while z % d:
        z = z * 10 + x
        k += 1
    return k, z / d

k繰り返しシーケンスの長さを追跡するため、たとえば1/9と1/99を区別できます)

この実装は(皮肉なことに)10進展開が有限の場合は永久にループしますが、無限の場合は終了することに注意してください!ただし、2または5でないn/dすべての素因数がに存在する場合のみ有限の10進表現を持つため、このケースを確認できます。dn


1
この答えは正しいようです。この方法は、「ルール」を以下に基づいています:0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)など
から来た

4
1/6または5/12のような場合に失敗します:\
razpeitia

1
@razpeitia類似したものを作成しましたが、すべての場合で動作します(整数除算を含む)。チェックアウト:codepad.org/hKboFPd2
ティグランサルエフ

github.com/Macil/cycle-divisionで@TigranSaluevに
Macil

2

長い分裂?:/

結果を文字列に変換してから、このアルゴリズムを適用します。文字列が通常の型で十分に長くない場合は、BigDecimalを使用します。


4
(問題だろう...とどのように0.121212312121231212123計算を停止したときに知っているのですか?)「を文字列にそれを回し、」任意精度計算や文字列の繰り返し部分の2つのコピーを計算するために非常に長い文字列を必要とする可能性があります
スパー

@Sparr繰り返しの長さは常に分母よりも小さくなります。

@MichaelT私はそれを知りませんでした。trueの場合、精度は正確に「任意」ではありませんが、分母に応じて任意に高くすることができます。
スパー

@Sparr math.stackexchange.com/questions/298844/...私が見つけるのにeverything2.com/title/recurring+decimalより読みやすいです。

リンク先のアルゴリズムが修正なしで機能するとは思わない。重複する繰り返しが含まれ、連続した一致だけでなく、文字列全体を検索します。たとえば、「banana」で最も長く繰り返される部分文字列は「ana」です。
Web_Designer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.