İki tamsayı a
ve b
nerede 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.
İki tamsayı a
ve b
nerede 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.
Yanıtlar:
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/n
normal 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.m
n-1
n
lambda(n)
m/n
phi(n)
phi(n)
phi
lambda(n)
n
Sayı teorim şu anda biraz paslı, bu yüzden yapabileceğimin en iyisi sizi bu yöne işaret etmektir.
İzin verin n < d
, ve yinelenen kısmını anlamaya çalışıyorsunuz n/d
. p
Tekrarlayan 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 p
1'den sonsuza kadar döngü yapın ve d
eş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
( k
yinelenen 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/d
tüm asal faktörler d
de mevcutsa , yalnızca sınırlı bir ondalık gösterime sahip olacaktır n
.
0.123123... = 123/999
0.714258714258... = 714258/999999 (=5/7)
vs
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.