Sto cercando di trovare un algoritmo efficiente in Java per trovare la parte decimale ripetuta di due numeri interi a
e b
dove a/b
.
per esempio. 5/7 = 0.714258 714258 ....
Attualmente conosco solo il metodo della divisione lunga.
Sto cercando di trovare un algoritmo efficiente in Java per trovare la parte decimale ripetuta di due numeri interi a
e b
dove a/b
.
per esempio. 5/7 = 0.714258 714258 ....
Attualmente conosco solo il metodo della divisione lunga.
Risposte:
Credo che ci siano due approcci generali qui, puoi essenzialmente "forza bruta" cercare la stringa ripetuta più lunga o puoi risolverla come un problema di teoria dei numeri.
È passato molto tempo da quando ho riscontrato questo problema, ma un caso speciale (1 / n) è il problema n. 26 su Project Euler, quindi potresti essere in grado di trovare maggiori informazioni cercando soluzioni efficienti per quel nome specifico. Una ricerca ci porta al sito Web di Eli Bendersky, dove spiega la sua soluzione . Ecco alcune delle teorie dalla pagina delle espansioni decimali di Mathworld :
Ogni frazione non regolare
m/n
è periodica e ha un periodolambda(n)
indipendente dam
, che èn-1
lungo al massimo di cifre. Sen
è relativamente primo a 10, allora il periodolambda(n)
dim/n
è un divisore diphi(n)
e ha al massimophi(n)
cifre, dovephi
è la funzione totient. Si scopre chelambda(n)
è l' ordine moltiplicativo di 10 (modn
) (Glaisher 1878, Lehmer 1941). Il numero di cifre nella parte ripetuta dell'espansione decimale di un numero razionale può anche essere trovato direttamente dall'ordine moltiplicativo del suo denominatore.
La mia teoria dei numeri è un po 'arrugginita al momento, quindi il meglio che posso fare è indicarti quella direzione.
Lascia n < d
, e stai cercando di capire la parte ripetitiva di n/d
. Sia p
il numero di cifre nella parte ripetuta: quindi n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...)
. La parte tra parentesi è una serie geometrica, uguale a 1/(10^p - 1)
.
Così n / d = R / (10^p - 1)
. Riorganizzare per ottenere R = n * (10^p - 1) / d
. Per trovare R, p
passa da 1 a infinito e fermati non appena si d
divide uniformemente n * (10^p - 1)
.
Ecco un'implementazione in 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
tiene traccia della lunghezza della sequenza ripetuta, in modo da poter distinguere tra 1/9 e 1/99, ad esempio)
Si noti che questa implementazione (ironicamente) viene ripetuta per sempre se l'espansione decimale è finita, ma termina se è infinita! Puoi verificare questo caso, perché n/d
avrà una rappresentazione decimale finita solo se d
sono presenti anche tutti i fattori primi che non sono 2 o 5 n
.
0.123123... = 123/999
0.714258714258... = 714258/999999 (=5/7)
ecc.
Lunga divisione? : /
Trasforma il risultato in una stringa e quindi applica questo algoritmo . Usa BigDecimal se la tua stringa non è abbastanza lunga con tipi normali.