Tests

Transcript

Tests
Cristiano Teodoro
(Ministero delle Comunicazioni – I.S.C.T.I.)
UN METODO PER IL CALCOLO VELOCE DEI NUMERI
DI FIBONACCI E DI LUCAS
(A METHOD FOR FAST COMPUTATION OF FIBONACCI AND LUCAS NUMBERS)
Sommario: viene descritto un algoritmo per il calcolo veloce del valore numerico dei numeri di
Fibonacci e di Lucas alternativo all'algoritmo classico ma elementare, di esecuzione lenta per il calcolo di
questi numeri se di indice elevato. Tali numeri trovano riscontri ed applicazioni in vari campi della scienza e
della tecnica, in particolare nel campo della moderna crittografia applicata alle telecomunicazioni.
Abstract: this paper presents a fast algorithm for esact computation of Fibonacci and Lucas numbers, in
alternative of classic trivial algorithm especially slower for high numbers .
Such numbers have different references and applications in several scientific and technical fields,
specifically in the modern cryptography applied to communications.
Questo breve articolo descrive un algoritmo per il calcolo veloce del valore numerico dei numeri di
Fibonacci e di Lucas.
Un argomento della teoria dei numeri che ha trovato molte applicazioni [1] nei più disparati campi della
scienza e della tecnica, dalla matematica alla fisica, dalla chimica alla biologia, dalla ricerca operativa
all’astronomia, ma soprattutto nella moderna crittografia, è quello riguardante le cosiddette Sequenze di Lucas
che sono in generale delle successioni ricorrenti di numeri interi chiamati termini in cui ogni termine è definito
come una certa funzione di quelli precedenti
Diverse applicazioni di tali sequenze e dei suddetti numeri si riscontrano nel campo delle
telecomunicazioni, quali ad esempio il calcolo della capacità di informazione di una sorgente discreta , l’analisi
spettrale di segnali elettrici.
Ma è soprattutto molto interessante il loro utilizzo nel campo della moderna crittografia (vedi [1], [2], [3],
[4], [5], [6], [7], oltre a diversi altri Siti Internet).
Questo breve articolo prendendo in considerazione due particolari sequenze descrive un algoritmo per il
calcolo veloce del valore numerico dei numeri di Fibonacci e di Lucas.
Prima di illustrare l’algoritmo sarà opportuno per chi è digiuno di questo argomento specifico dire in
breve qualcosa su questi numeri.
Prendiamo in esame due particolari sequenze o successioni ricorrenti di numeri, di cui si danno i primi
13 termini partendo dal primo termine :
1a successione:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,144, ……….
2a successione:
2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199, ……….
Come si costruiscono i termini della successione seguenti a quelli mostrati?
Definiamo innanzi tutto il termine generico della 1a successione come U(k) dove k prende il nome di
indice.
Detta successione può essere genericamente indicata così:
U(0),U(1),U(2),U(3),U(4),U(5),U(6),U(7),U(8), U(9),U(10),U(11),U(12),.…………U(k), ………….
E’ facile vedere, tenendo conto dei valori numerici mostrati, che U(k), ad esclusione dei primi due
termini, è legato ai termini precedenti dalla seguente relazione:
U(k) = U(k-1) + U(k-2)
per cui, ad esempio, il termine U(13) seguentea U(12) =144 è il numero 233.
Tale successione viene denominata sequenza di Fibonacci.
Analogamente definiamo il termine generico della 2a successione associata (companion sequence) alla
sequenza di Fibonacci come V(k).
Questa successione può essere indicata come segue:
V(0), V(1), V(2), V(3), V(4), V(5), V(6), V(7), V(8), V(9), V(10), V(11),…......…V(k)., ……............
Anche per detta successione si vede che V(k) = V(k-1) + V(k-2) per cui allora il termine V(12) seguente
a V(11) =199 è il numero 322.
In effetti, se si osservano i valori numerici sopraelencati ci si accorge che ciascun valore è dato dalla
somma dei due valori immediatamente ad esso precedenti.
I generici termini U(k) e V(k) sono chiamati rispettivamente numeri di Fibonacci e numeri di Lucas.
Tra le diverse Sequenze di Lucas, vogliamo qui citare una successione numerica ricorrente molto
importante nella ricerca di numeri primi molto grandi della forma 2p-1, con p primo, chiamati numeri di
Mersenne e indicati con il simbolo Mp. Essa è la seguente: S(k) = S(k-1)2 – 2 di cui il termine iniziale è 4.
I primi cinque 5 termini di questa successione saranno pertanto 4, 14, 194, 37634, 1416317954.
Con l’utilizzo appropriato di tale successione, (i cui termini , se superano il valore numerico Mp preso
in considerazione, sono calcolati “modulo Mp” e cioè quali resti della divisione di S(k) per Mp), sono stati
scoperti tutti i numeri primi più grandi calcolati sinora (primi di Mersenne) costituiti addirittura da milioni di
cifre [8] .
Ma torniamo ai numeri di Fibonacci e di Lucas argomento di questo breve articolo il cui scopo è solo
quello di illustrare un metodo alternativo e molto più efficiente rispetto a quello classico che utilizza
semplicemente la formule ricorrenti:
U(k)=U(k-1) + U(k-2) con U(0) = 0 e U(1) =1 ; V(k) = V(k-1) + V(k-2) con V(0) =2 e V(1) =1
per il calcolo rispettivamente del valore numerico di U(k) e di V(k).
L’efficienza del metodo viene messa in evidenza soprattutto quando si vanno a calcolare valori dei
numeri di Fibonacci o di Lucas di indice grande.
Naturalmente per detti numeri, a partire da valori numerici costituiti da più di 15 cifre, sarà necessario
sviluppare con un adeguato linguaggio programmi dotati di istruzioni per una aritmetica a precisione multipla,
cioè con una precisione di calcolo molto superiore a quella massima (doppia precisione) disponibile
normalmente su un PC .
L’algoritmo proposto si presta bene ad essere programmato e utilizzato in aritmetica a precisione multipla.
In questo articolo ci si limiterà pertanto ad illustrare per ora le formule e le relazioni esistenti tra i
numeri di Fibonacci e di Lucas di diverso indice che risultano le più adeguate allo scopo, cioè al calcolo del
valore numerico di U(z) e di V(z) dove z è un indice anche di valore elevato, ( ad esempio z =1000 oppure z
=10000 o z =250.000), rimandando ad altra occasione il programma completo, costituito da istruzioni espresse
nel linguaggio QBASIC con cui si realizza il calcolo del valore esatto dei numeri U(z) e V(z).
Si fa presente che per valori dell’indice z grande i valori numerici di U(z) e V(z) possono esser
composti da moltissime cifre ( se ad esempio U(100) è composto “solo” da 21 cifre, mentre U(100.000) è
costituito da ben 20.899 cifre.
Le formule e relazioni che si utilizzano, ricavate da quelle riportate in [9] sono le seguenti:
- per un indice z pari, posto z = 2· x
U(z) = U(2· x) = U(x)· V(x) V(z) = V(2· x) = V(x)2 – 2· (-1)x
- per un indice z dispari, posto z = 2· x + 1 e tenendo conto delle seguente relazioni [9] :
2· U(k+h) = U(k)· V(h) + U(h)· V(k)
2· V(k+h) = V(k)· V(h) + 5· U(k)· U(h)
considerando ora k = 2· x, h =1 si trova:
2· U(z) = 2· U(2· x +1) = U(2· x)· V(1) + U(1)· V(2· x) = U(2· x ) + V(2· x)
2· V(z) = 2· V(2· x +1) =V(2· x )· V(1) + 5· U(2· x)· U(1)= V(2· x ) + 5· U(2· x)
in quanto U(1) = 1; V(1) = 1
ma:
U(2· x) = U(x)· V(x) e V(2· x) = V(x)2 – 2(-1)x
per cui le formule suddette risulteranno così modificate:
2· U(2· x +1) = U(x)· V(x) + V(x)2 – 2(-1)x
2· V(2· x +1) = V(x)2 + 5· U(x)· V(x) – 2(-1)x
Da queste formule si può vedere che i valori U(z) e V(z) dipendono esclusivamente dall’indice x e dai
valori U(x) e V(x), dove x è la metà di z per z pari, mentre x è dato da (z - 1) / 2 per z dispari .
Consideriamo ora un qualsiasi indice z : posto x0 = z si può sempre trovare a partire da x0 una successione
limitata di indici di valore numerico decrescente:
x0, x1, x2, x3, x4, x5, …….. xk-1, xk , xk+1,…….xn-1, xn
con xn = 1 ultimo termine, tale da rispettare le seguenti regole:
se il generico indice xk è di valore pari si pone
xk+1 = xk / 2,
se xk è dispari si pone
xk+1 = (xk - 1) / 2
Si mette in evidenza che il numero degli indici a partire da x0 = z sino a xn =1 risulta limitato ad un
valore pari al più piccolo intero maggiore od uguale a log(z) / log2, dove il simbolo log indica il logaritmo in
base 10; ad esempio per un indice z =100.000 il numero totale degli indici è 17.
Partendo dall’indice xn = 1 per il quale si ha U(xn) = 1 e V(xn) = 1 si possono calcolare con le formule
date sopra i valori di U(xn-1) e di V(xn-1) relativi all’indice xn-1, sia che esso risulti di valore pari o di valore
dispari.
Proseguendo quindi passo a passo con gli altri indici xk della successione relativa all’indice iniziale x0 =
z, si arriverà ai valori cercati di U(xo) e di V(xo) con un ciclo limitato di iterazioni iz = |_ log(z)/log2_| .
Pertanto ad ogni iterazione utilizzando i valori U(xk) e V(xk) si passa ai valori U(xk-1) e V(xk-1) dove
l’indice xk-1 se è pari è il doppio dell’indice xk, se dispari è il doppio di xk aumentato di 1.
Un semplice esempio chiarirà quanto detto.
Si voglia trovare il valore di U(59) e di V(59).
Partendo ad esempio da x0 = z = 59, con U(0) = 1, V(0) = 1 e indicando con il verso delle frecce
l’andamento temporale delle iterazioni si può schematizzare così il procedimento di calcolo:
Come già osservato l’algoritmo sopra accennato si presta bene ad essere sviluppato in aritmetica a
precisione multipla.
Si potrebbe pensare di utilizzare le formule di Binet che sono delle formule compatte per il calcolo di
U(z) e di V(z); ma esse non risultano molto convenienti per il calcolo esatto di tutte la cifre di cui sono
composti U(z) e V(z), anche per valori dell’indice z non molto grandi, in quanto esse presentano a denominatore
V5 che è un numero irrazionale.
Per finire si dà un esempio di paragone di tempo di esecuzione relativo al calcolo di U(z) e V(z) fra i due
tipi di algoritmi: quello classico ma banale, e quello illustrato nella presente nota, per un indice
z =100.000
(centomila)
- col metodo classico, utilizzando un normale PC (450 MHz) il tempo di esecuzione per il calcolo del
valore esatto di U(100.000), che è un numero costituito da 20899 cifre decimali, è risultato pari a 3 ore e 48
minuti;
- col presente algoritmo, sempre con l’utilizzo dello stesso PC, il tempo di esecuzione per trovare non solo
il valore di U(100.000) ma contemporaneamente anche quello di V(100.000) è risultato di 4 minuti e 6
secondi..
Tale differenza di tempi è facilmente spiegabile in quanto con l’algoritmo classico per trovare il valore di
U(100.000) occorre effettuare pedissequamente il calcolo di tutti i precedenti numeri di Fibonacci , con un
ciclo di 100.000 iterazioni, mentre con l’algoritmo illustrato è sufficiente, pur con calcoli aritmetici più
complessi in ogni iterazione, un ciclo di sole 16 iterazioni.
RIFERIMENTI
[1] P. Filipponi: “I numeri di Fibonacci ” – Sistemi di Telecomunicazioni, n.12,dicembre 1989
[2] A. Bosselaers, P. Filipponi, B. Preneel : “Su alcuni aspetti numerici degli pseudoprimi di Fibonacci”Note Recensioni Notizie, v.38, n.1-2 ,gennaio-giugno 1989
[3] P. Filipponi, E. Montolivo : “Representation of natural numbers as sum of Fibonacci numbers:
an application to modern cryptography” – Application of Fibonacci Numbers, v. 3, Kluwer Academic
Publishers, Dordrecht (NL) 1990
[4] A. Di Porto, P. Filipponi, E. Montolivo: “On generalized Fibonacci pseudoprimes”- TheFibonacci Quaterly,
v,29, novembre1990
[5] “Lucas Sequences in Cryptography”- Sito internet htpp://www.amasci.com/~weidai/lucas.html
[6] “Periods of Fibonacci Sequences Mod m”- Sito Internet htpp:/www.mathpages.com/home/kmath078.htm
[7] “Lucas Sequences and cryptography”- Sito Internet tpp://saturn.hut.fi/~helger/crypto/link/public/luc.html
[8]“MersennePrime: Histoty,Theoremsand List“Sito Internet: tpp://www.utm.edu/research/primes/mersenne/index.html
[9] P. Ribenboin - The little book of big primes: pagg. 38,39 – Springer-Verlag