Saya mencoba untuk menemukan algoritma yang efisien di Jawa untuk menemukan bagian desimal berulang dari dua bilangan bulat a
dan di b
mana a/b
.
misalnya. 5/7 = 0.714258 714258 ....
Saat ini saya hanya tahu metode pembagian panjang.
Saya mencoba untuk menemukan algoritma yang efisien di Jawa untuk menemukan bagian desimal berulang dari dua bilangan bulat a
dan di b
mana a/b
.
misalnya. 5/7 = 0.714258 714258 ....
Saat ini saya hanya tahu metode pembagian panjang.
Jawaban:
Saya percaya bahwa ada dua pendekatan umum di sini, Anda pada dasarnya dapat "brute force" mencari string berulang berulang, atau Anda dapat menyelesaikannya sebagai masalah teori bilangan.
Sudah lama sejak saya menemukan masalah ini, tetapi kasus khusus (1 / n) adalah masalah # 26 di Project Euler, jadi Anda mungkin dapat menemukan informasi lebih lanjut dengan mencari solusi efisien untuk nama spesifik tersebut. Satu pencarian membawa kita ke situs web Eli Bendersky, tempat dia menjelaskan solusinya . Berikut beberapa teori dari halaman Desimal Ekspansi Mathworld :
Setiap fraksi tidak beraturan
m/n
bersifat periodik, dan memiliki periode yang tidaklambda(n)
bergantung padam
, yang palingn-1
panjang digit. Jikan
relatif prima terhadap 10, maka periodelambda(n)
darim/n
adalah pembagi dariphi(n)
dan memiliki paling banyakphi(n)
digit, dimanaphi
adalah fungsi totient. Ternyata itulambda(n)
adalah urutan multiplikasi 10 (modn
) (Glaisher 1878, Lehmer 1941). Jumlah digit dalam bagian berulang dari ekspansi desimal dari bilangan rasional juga dapat ditemukan langsung dari urutan multiplikatif dari penyebutnya.
Teori bilangan saya agak berkarat saat ini, jadi yang terbaik yang bisa saya lakukan adalah mengarahkan Anda ke arah itu.
Biarkan n < d
, dan Anda mencoba mencari tahu bagian yang berulang n/d
. Membiarkan p
menjadi jumlah digit di bagian berulang: lalu n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...)
. Bagian kurung adalah deret geometris, sama dengan 1/(10^p - 1)
.
Jadi n / d = R / (10^p - 1)
. Atur ulang untuk mendapatkan R = n * (10^p - 1) / d
. Untuk menemukan R, loop p
dari 1 hingga tak terbatas, dan berhenti segera setelah d
membagi secara merata n * (10^p - 1)
.
Berikut ini adalah implementasi dengan 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
melacak panjang urutan berulang, sehingga Anda dapat membedakan antara 1/9 dan 1/99, misalnya)
Perhatikan bahwa implementasi ini (ironisnya) berulang selamanya jika ekspansi desimal terbatas, tetapi berakhir jika tidak terbatas! Anda dapat memeriksa kasus ini, karena n/d
hanya akan memiliki representasi desimal terbatas jika semua faktor prima d
yang bukan 2 atau 5 juga ada n
.
0.123123... = 123/999
0.714258714258... = 714258/999999 (=5/7)
dll.
Divisi panjang? : /
Ubah hasilnya menjadi string, dan kemudian terapkan algoritma ini ke sana. Gunakan BigDecimal jika string Anda tidak cukup panjang dengan tipe biasa.