Qui vorrei dare un'altra euristica, che è diversa da quella di btilly.
Il compito è quello di trovare interi m
e n
tale che m/n <= j < k <= (m + 1)/n
, con n
più grande possibile (ma ancora in fase di M
).
Intuitivamente, è preferibile che la frazione m/n
sia vicina a j
. Questo porta all'idea di utilizzare continued fractions.
L'algoritmo che vi propongo è molto semplice:
- calcolare tutte le continue frazioni di
j
utilizzando segni meno (in modo che le frazioni sono sempre approching j
dall'alto), fino a quando il denominatore supera M
;
- per ogni tale frazione
m/n
, trovare il più grande intero i >= 0
tale che k <= (m * i + 1)/(n * i)
e n * i <= M
, e sostituire la frazione m/n
con (m * i)/(n * i)
;
- tra tutte le frazioni in 2, trova quella con il più grande denominatore.
L'algoritmo non è simmetrico in j
e k
. Quindi c'è una simile versione , che in generale non dovrebbe dare la stessa risposta, in modo che tu possa scegliere quella più grande tra i due risultati.
Esempio: Qui mi prenderò del btilly esempio: j = 0.6
e k = 0.65
, ma io prenderò M = 10
.
Per prima cosa analizzerò la procedura j
. Per calcolare l'espansione frazione continua di j
, calcoliamo:
0.6
= 0 + 0.6
= 0 + 1/(2 - 0.3333)
= 0 + 1/(2 - 1/(3 - 0))
Dal 0.6
è un numero razionale, l'espansione termina in fintely molti passi. Le frazioni corrispondenti sono:
0 = 0/1
0 + 1/2 = 1/2
0 + 1/(2 - 1/3) = 3/5
Computing corrispondenti i
valori nel passaggio 2, si sostituisce le tre fazioni con:
0/1 = 0/1
1/2 = 3/6
3/5 = 6/10
Il più grande denominatore è dato da 6/10
.
Continuare con l'esempio precedente, la corrispondente k
-procedure va come segue:
0.65
= 1 - 0.35
= 1 - 1/(3 - 0.1429)
= 1 - 1/(3 - 1/(7 - 0))
Quindi le corrispondenti frazioni:
1 = 1/1
1 - 1/3 = 2/3
1 - 1/(3 - 1/7) = 13/20
Passando passo 2, si ottiene:
1/1 = 2/2
2/3 = 6/9
13/20 = 0/0 (this is because 20 is already bigger than M = 10)
Il più grande denominatore è dato da 6/9
.
MODIFICA: risultati sperimentali.
Con mia sorpresa, l'algoritmo funziona meglio di quanto pensassi.
Ho fatto il seguente esperimento, con il limite M
ignorato (equivalentemente, uno può prendere M
abbastanza grande).
In ogni round, viene generata una coppia (j, k)
di numeri casuali distribuiti uniformemente nell'intervallo [0, 1)
con j < k
. Se la differenza k - j
è inferiore a 1e-4
, scartare questa coppia, rendendo questo turno inefficace. In caso contrario, calcolo il vero risultato trueN
utilizzando l'algoritmo naive e calcola il risultato euristico heurN
utilizzando il mio algoritmo e li aggiungo ai dati statistici. Questo vale per 1e6 round.
Ecco il risultato:
effective round = 999789
sum of trueN = 14013312
sum of heurN = 13907575
correct percentage = 99.2262 %
average quotient = 0.999415
Il correct percentage
è la percentuale di giri effettivi tale che trueN
è uguale a heurN
, e il average quotient
è la media del quoziente heurN/trueN
per tutti i turni efficaci.
Così il metodo fornisce la risposta corretta nel 99% + casi.
Ho eseguito anche esperimenti con valori minori M
e i risultati sono simili.
Hai davvero bisogno di una risposta esatta? O semplicemente un buon euristico? – btilly
Non deve essere il valore migliore effettivo per N, ma non può sovrastimare. IE: la gamma deve essere effettivamente interamente all'interno di un cestino, non possiamo fondere un po 'e farlo fuoriuscire. Quindi suppongo che direi che l'algoritmo deve essere "conservativo". –
Ti ho dato un euristico "conservatore". Trasformarlo in "trova la risposta migliore" sarebbe complicato e renderebbe il tempo di esecuzione molto lungo. Molto meglio dell'algoritmo ingenuo, ma l'euristica offre probabilmente risposte abbastanza buone da non disturbare. – btilly