yinelenen ondalık bulmak için etkili bir yol nedir


24

İki tamsayı ave bnerede yinelenen ondalık bölümünü bulmak için Java etkin bir algoritma bulmaya çalışıyorum a/b.

Örneğin. 5/7 = 0.714258 714258 ....

Şu anda sadece uzun bölümleme yöntemini biliyorum.


2
Yani a = 5 ve b = 7 değerlerine sahipsiniz ve a / b'yi kayan nokta ile kolayca kolayca hesaplayabilirsiniz, ama bilmek istediğiniz 6 ondalık basamaktan sonra tekrar ettiği anlamına mı geliyor?
Sparr

Yanıtlar:


10

Burada iki genel yaklaşım olduğuna inanıyorum, esasen en uzun yinelenen dize için "kaba kuvvet" arayabilir veya sayı teorisi sorunu olarak çözebilirsiniz.

Bu sorunla karşılaştığımdan bu yana çok zaman geçti, ancak özel bir durum (1 / n) Proje Euler'de 26. sırada, bu nedenle bu belirli ad için etkili çözümler arayarak daha fazla bilgi bulabilirsiniz. Bir arama bizi Eli Bendersky'nin web sitesine götürür ve çözümünü açıklar . İşte Mathworld'ün Ondalık Açılımlar sayfasındaki teorinin bir kısmı :

Herhangi bir m/nnormal olmayan kesir periyodiktir ve en fazla rakam uzunluğunda olan, lambda(n)bağımsız bir süreye sahiptir . Eğer o zaman periyodu, 10 aralarında asal olduğu bir bir bölen bir ve en fazla sahip basamağı, totient işlevidir. 10'un çarpımsal sırası olduğu ortaya çıkıyor (mod ) (Glaisher 1878, Lehmer 1941). Bir rasyonel sayının ondalık genişlemesinin tekrarlayan bölümündeki hane sayısı doğrudan paydasının çarpım sırasından da bulunabilir.mn-1nlambda(n)m/nphi(n)phi(n)philambda(n)n

Sayı teorim şu anda biraz paslı, bu yüzden yapabileceğimin en iyisi sizi bu yöne işaret etmektir.


8

İzin verin n < d, ve yinelenen kısmını anlamaya çalışıyorsunuz n/d. pTekrarlayan kısımdaki hane sayısı olsun : o zaman n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...). Parantezli kısım, eşittir geometrik bir seridir 1/(10^p - 1).

Yani n / d = R / (10^p - 1). Almak için yeniden düzenleyin R = n * (10^p - 1) / d. R'yi bulmak için p1'den sonsuza kadar döngü yapın ve deşit olarak bölündüklerinde durun n * (10^p - 1).

İşte Python'da bir uygulama:

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

( kyinelenen dizinin uzunluğunu izler, böylece 1/9 ile 1/99 arasında ayrım yapabilirsiniz)

Bu uygulamanın (ironik olarak), ondalık genişlemenin sonlu olması durumunda sonsuza kadar döngüye girdiğini, ancak sonsuz olması durumunda sona erdiğini unutmayın! Yine de, bu durumu kontrol edebilirsiniz çünkü 2 veya 5 olmayan n/dtüm asal faktörler dde mevcutsa , yalnızca sınırlı bir ondalık gösterime sahip olacaktır n.


1
Bu cevap doğru görünüyor. Yöntemi "kuralı" Aşağıdaki dayanmaktadır: 0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)vs
GELMEKTEDİR

4
1/6 veya 5/12 gibi durumlarda başarısız olur: \
razpeitia

1
@razpeitia Benzer bir şey yaptım ama her durumda çalışıyorum (tamsayı bölme dahil). Çıkış: codepad.org/hKboFPd2
Tigran Saluev


2

Uzun bölüm? : /

Sonucu bir dizgeye çevirin ve bu algoritmayı ona uygulayın. Dizeniz sıradan türlerle yeterince uzun değilse, BigDecimal kullanın.


4
(Bir sorun olacağını ... ve nasıl 0,121212312121231212123 hesaplama durdurmak için ne zaman biliyor musunuz?) "Bir dizeye çevirin" keyfi hassas hesaplamalar ve dizesinin tekrar kısmının iki kopyasını hesaplamak için çok uzun bir dize gerektirebilir
Sparr

@Sparr Tekrarın uzunluğu daima paydadan küçüktür.

@MichaelT Bunun farkında değildim. Doğruysa, hassasiyet tam olarak "keyfi" değildir, ancak paydaya bağlı olarak keyfi olarak yüksek olabilir.
Sparr

@Sparr math.stackexchange.com/questions/298844/… her şeyi2.com/ title/ recurring+ decimal daha okunabilir bulabilirim .

Bağlandığınız algoritmanın değiştirilmeden çalışacağını sanmıyorum. Örtüşen tekrarları içerir ve tüm dizgiyi arar (sadece ardışık eşleşmeler için değil). Örneğin, "muz" da tekrarlanan en uzun alt-tabaka "ana" dır.
Web_Designer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.