begin process at 2012 02 07 09:09:04
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > FIBONACCI EN O( N )

FIBONACCI EN O( N )


 Information sur la source

Note :
Aucune note
Catégorie :Maths & Algorithmes Classé sous :fibonacci, algorithme, fibonnacci Niveau :Débutant Date de création :24/07/2004 Date de mise à jour :24/07/2004 20:55:26 Vu :8 023

Auteur : ZogStriP

Ecrire un message privé
Site perso
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (25)
Ajouter un commentaire et/ou une note


 Description

Cliquez pour voir la capture en taille normale
Ce code permet de trouver le nombre n de la suite de fibonacci !
Le code est en O( n ) se qui accroit grandement sa vitesse !

Vous pouvez facilement avoir le 10^7ieme nombre de la suite de Fibonacci, aprés ça devient un peu long...

Source

  • #include <stdio.h>
  • typedef unsigned long int ULONG;
  • void MultiMatrice(ULONG Matrice1[][2], ULONG Matrice2[][2], ULONG MatriceResultat[][2])
  • {
  • int i,j,k;
  • for(i = 0; i < 2; i++)
  • {
  • for(j = 0; j < 2; j++)
  • {
  • MatriceResultat[i][j] = 0;
  • for(k = 0; k < 2; k++)
  • MatriceResultat[i][j] += Matrice1[i][k] * Matrice2[k][j];
  • }
  • }
  • }
  • void CopieMatrice(ULONG Matrice1[][2], ULONG Matrice2[][2])
  • {
  • int i,j;
  • for(i = 0; i < 2; i++)
  • for(j = 0; j < 2; j++)
  • Matrice1[i][j] = Matrice2[i][j];
  • }
  • int main(void)
  • {
  • int Nombre, n;
  • ULONG Matrice[2][2] = {{0,1},{1,1}};
  • ULONG resMatrice[2][2], tmpMatrice[2][2];
  • CopieMatrice(tmpMatrice, Matrice);
  • scanf("%lu",&Nombre);
  • if(Nombre <= 0)
  • {
  • printf("Le resultat est : 0");
  • getch();
  • return 0;
  • }
  • // On cherche la puissance N de la matrice :
  • // Le problème c'est que c'est en O( n ) pour l'instant !
  • for(n = 0; n < Nombre; n++)
  • {
  • MultiMatrice(tmpMatrice, Matrice, resMatrice);
  • CopieMatrice(tmpMatrice, resMatrice);
  • }
  • printf("Le resultat est : %lu", resMatrice[0][0]);
  • // F(n+1) ==> resMatrice[1][1] !
  • getch();
  • return 0;
  • }
#include <stdio.h>

typedef unsigned long int ULONG;
                    
void MultiMatrice(ULONG Matrice1[][2], ULONG Matrice2[][2], ULONG MatriceResultat[][2])
{
    int i,j,k;
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            MatriceResultat[i][j] = 0;
            for(k = 0; k < 2; k++)
                MatriceResultat[i][j] += Matrice1[i][k] * Matrice2[k][j];
        }
    }
}

void CopieMatrice(ULONG Matrice1[][2], ULONG Matrice2[][2])
{
    int i,j;
    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            Matrice1[i][j] = Matrice2[i][j];
}
                  
int main(void)
{
    int Nombre, n;
    ULONG Matrice[2][2] = {{0,1},{1,1}};
    ULONG resMatrice[2][2], tmpMatrice[2][2];
    CopieMatrice(tmpMatrice, Matrice);
    
    scanf("%lu",&Nombre);
    if(Nombre <= 0)
    {
        printf("Le resultat est : 0");
        getch();
        return 0;
    }
    
    // On cherche la puissance N de la matrice :  
    // Le problème c'est que c'est en O( n ) pour l'instant !      
    for(n = 0; n < Nombre; n++)
    {
        MultiMatrice(tmpMatrice, Matrice, resMatrice);
        CopieMatrice(tmpMatrice, resMatrice);
    }

    printf("Le resultat est : %lu", resMatrice[0][0]);
    // F(n+1) ==> resMatrice[1][1] !
    
    getch();
    return 0;
}

 Conclusion

Si vous savez comment faire pour rendre le code plus rapide, n'hésitez surtout pas ;)


 Historique

24 juillet 2004 11:42:51 :
Mise à jour permmettant de dépasser l'erreur du modulo 2^32 des int
24 juillet 2004 20:54:13 :
Amélioration du code !
24 juillet 2004 20:55:26 :
Dépouillement du code des bugs !

 Sources de la même categorie

Source avec Zip UN EXAMPLE D'APPLICATION EN CUDA DE L'ALGORITHME DE SCAN POU... par oguzaras
Source avec Zip Source avec une capture CHIFFREMENT DE VIGENERE par lajouad
Source avec Zip Source avec une capture ANALYSE SYNTAXIQUE par lajouad
Source avec Zip Source avec une capture STRUCTURE D'UNE MATRICE PAR LES LISTE LINÉAIRE (NON CONTUGUS... par benzarabel
Source avec Zip Source avec une capture DESSINER UNE ARBRE BINAIRE( MODE CONSOLE): par benzarabel

 Sources en rapport avec celle ci

Source avec Zip UN EXAMPLE D'APPLICATION EN CUDA DE L'ALGORITHME DE SCAN POU... par oguzaras
Source avec Zip Source avec une capture RÉSOLUTION SUDOKU (9X9) PAR BACKTRACKING RÉCURSIF INTELLIGEN... par Gallien69
GÉRER UN COMBAT DANS UN JEU 2D / ALGORITHME PRIMAIRE D'UNE I... par Chiheb2010
Source avec Zip BELLMAN:LA VALEUR DU PLUS COURT CHEMIN ET LE PLUS COURT CHEM... par Perace
Source avec Zip COMPRESSION / DECOMPRESSION SELON L'ALGORITHME LEMPELZIV 78V par th1man

Commentaires et avis

Commentaire de MetalDwarf le 24/07/2004 11:28:05

Oui je connais cette methode je l ai eu en DS d'info. C'est d'ailleurs etonnant que l algorithme "naturel" soit exponentiel, que le plus reflechi en O(n) et  celui-la en O(log(n)). Ce qui est egalement troublant c est le fait que cette formule n ai pas de rapport a priori avec la suite de fibonacci (meme si demontrer la correction de cet algorithme n est pas dur du tout).

Commentaire de ZogStriP le 24/07/2004 11:44:28 administrateur CS

J'ai lu sur une autre source :

"Il y a une méthode pour accélérer le tout de facon draconnienne (complexité en log(n) au lieu de n)
- on remarque que [[0,1][1,1]]^n a pour element en haut à gauche fibo(n)
- pour calculer a^n efficacement ,on utilise
a^(2*p)=(a*a)^p et a^(2*p+1)=a*((a*a)^p)"

Ca m'a l'air d'être plus rapide que mes boucles !
Si quelqu'un sait comment implémenter ça ;)

Commentaire de MetalDwarf le 24/07/2004 11:51:50

A oui c est vrai, je n avais pas regarde bien en detail ton code source.
Si tu veux que ton algo soit vraiment en O(log(n)), il faut imperativement utiliser l'algorithme d'exponentiation rapide sinon tu restes en O(n).
Il est tres simple a implementer, et il est naturellement recursif.

int exp_rap(int a, int n)
{
   int tmp;
   if(n=1) return 1;
   if(n%2)   // n impair
   {
       tmp = exp_rap(a,n/2);
       return (tmp*tmp)*a;
   }
    // n pair
   tmp = exp_rap(a,n/2);
    return tmp*tmp;
}

Bien sur vu que tu utilises des matrices il faut remplacer * par le produit des matrices.

Commentaire de coucou747 le 24/07/2004 13:39:48 administrateur CS

c'est pas ce nombre qui s'aproche du nombre d'or plus n est grand ?

Commentaire de Xs le 24/07/2004 14:38:35

Si, lim (n->+oo) (Un+2 = Un+Un+1) = (1+Rac(5))/2

D'ailleurs, une manniere assez rapide le n-ieme terme de la suite de fibonacci est :

(si on part de U0 en 1er terme et non pas U1)

Un+1 = 1/Rac(5) * (L^n + L_barre^n)

ou L est la limite, donc (1+Rac(5))/2 et L_Barre le conjugué ((1-Rac(5)/2).

C'est, je pense, assez rapide (plus rapide que cet algo je pense), puisque n est naturel

Commentaire de coucou747 le 24/07/2004 14:54:07 administrateur CS

Ok merci, mais bon, je comprends vraiment pas grand chose a ce que vous dites...

Commentaire de Xs le 24/07/2004 14:57:16

Tu comprends pas quoi ? Dis moi que j'essaie de t'expliquer :D

Commentaire de coucou747 le 24/07/2004 15:02:59 administrateur CS

pouriez vous expliquer clairement comment fonctionne cette suite... (je rentre en première S alors les math, je connais, mais pas a haut niveau, et la progbah un peu mais pas trop non plus)
Comment cette suite se fait elle ?
A quoi ça corespond ?
(1+Rac(5))/2 ça je comprends, c'est le nombre d'or, mais le reste...
Je sais pas pose clairement tes variables ou explique a quoi ça coresponds, la moi, je reste coincé... (même si ce problème n'est pas dans mes projets actuels, j'aime bien les math alors je me renseigne.)

Commentaire de Xs le 24/07/2004 16:06:57

Re !

"Comment cette suite se fait elle ?"
=> Reformule ta question stp, je ne comprend pas trés bien ce qu'elle veut dire. Si tu demandes d'ou on la sort, faut voir pour la petite histoire des lapins de F.

Si tu parles de "comment calculer Un" :

Une suite est en faite une fonction adaptée pour N (donc l'application U:N->R alors qu'une fct est f:R->R ou dans le genre)
C'est a dire que (Un) est le n-ieme terme de la suite, et que n est un entier naturel (0,1,2,....)

Dans le cas de F., si on te donne U(0) = 0 et U(1) = 1, pour calculer
U(2) tu fais, sachant que U(n+2) = U(n) + U(n+1)
n+2 = 2 <=> n = 0

donc

U(0+2) = U(0) + U(0+1)
<=> U(2) = U(0) + U(1)
<=> U(2) = 0 + 1
<=> U(2) = 1

U(3) = U(1) + U(2)
<=> U(3) = 1 + 1
<=> U(3) = 2

U(4) = U(2) + U(3)
<=> U(4) = 1 + 2 = 3

etc.... (u(5) = 5 ; u(6) = 8 ; u(7) = 13....)

Mes variables, je suppose L et L_barre sont juste des lettres que j'ai prises pour remplacer ce nombre d'or dont l'ecriture dans une equation en ANSII est assez casse pieds et encore plus à lire.

L_barre est le conjugué de ce nombre. Le conjugué de a+b est a-b. donc L_barre = (1-Rac(5))/2.

Pour ma "formule", c'est mon prof de maths qui me l'a donné, sans la démontrer (enfin si, mais j'ai rien compris à ses histoires d'espaces vectoriel, linéarité,etc...)

Ah ui, L est la limite de la suite de F. C'est a dire que plus "n" devient grand, plus on prend n aussi grand que l'on veut, plus U(n) aura des valeurs proches de 1.668.... ((1+Rac(5))/2)

Voici la démo (enfin.. les fractions continues ne sont pas une démo à mon gout mais bon)
http://www.sciences-en-ligne.com/momo/chronomath/anx3/suite_fibo.html

J'epere que tu auras compris ce que je t'ai expliqué... mais sache que faire plus précis va m'etre difficile car je ne suis qu'en TS (ex-1er S :D)


cordailement

Commentaire de MetalDwarf le 24/07/2004 16:42:08

non non non on ne peux pas dire que cette suite converge vers le nombre d'or puisque c est faux!!
en effet elle diverge vers +oo !!

Je crois par contre que cette limite est vraie :
           un+1
lim      -------  = (1+Rac(5))/2
n->oo   un

est correcte.

Quant a la methode presentee ici pour calculer cette suite, elle utilise les matrices (niveau 1ere annee de DEUG MIAS ou math sup)

Commentaire de coucou747 le 24/07/2004 16:55:25 administrateur CS

ah oui, c'est les lapins quse multiplient tout les 4 mois...
Qqn dans ma classe avait le nombre d'or comme thème d'étude...

Donc, cette "fonction" si j'ai bien compris, donne :
f(x)=f(x-1)+f(x-2)
et évidement, x ne peut pas être infèrieur a deux car avec un seul lapin, on a rien...
Mais ceci c'est une fonction f:N->N
et ça ne va pas vers le nombre d'or...

Commentaire de ZogStriP le 24/07/2004 20:57:58 administrateur CS

Le problème c'est que les suites ne sont pas vraiment des fonctions (enfin si, mais non en fait ;)

Tu apprendras tout ça en 1Ere S c'est au programme ( et je peux te dire que je m'en souvient... 21/20 au contrôle)

Sinon, j'ai trouvé l'exponentiation rapide en itératif :

ULONG exponentiation_rapide(int Nombre, int Puissance)
{
    ULONG resultat = 1lu;
    while (Puissance != 0)
    {
        // si Puissance est impair :
        if(Puissance % 2)
            resultat *= Nombre;
        Nombre *= Nombre;
        Puissance /= 2;
    }
    return resultat;
}

Le problème c'est que je n'arrive pas à l'implémenter avec les Multiplications de matrice...
MetalDwarf, tu peux m'aider ?

Commentaire de coucou747 le 24/07/2004 21:01:46 administrateur CS

je ne compredns pas vraiment ce que tu veux faire, mais si tu veux, j'ai un truc qui permet de faire a=i^d%n
on s'en sert en cryptographie rsa

Commentaire de ZogStriP le 25/07/2004 00:59:55 administrateur CS

Merci bcp coucou747 mais j'en ai pas besoin ;)

Je souhaiterais simplement "changer" l'algo pour qu'il fonctionne avec les multiplication des matrices et non des nombres !

Commentaire de MetalDwarf le 25/07/2004 11:07:08

Ba je ne vois pas trop ou est le probleme!!
Est ce que tu as une fonction de multiplication des matrices 2x2. Si non tu peux facilement en faire une qui aurait comme prototype :

int [2][2] mult_mat(int mat1[2][2],int mat2[2][2]);

a partir de la ton algo devient :

int [2][2] exponentiation_rapide(int mat[2][2], int Puissance)
{
    int resultat[2][2] = {{1,0],{0,1}};  // la matrice unite
    while (Puissance != 0)
    {
        // si Puissance est impair :
        if(Puissance % 2)
            resultat = mult_mat(resultat,mat);
        mat = mult_mat(mat,mat);
        Puissance /= 2;
    }
    return resultat;
}

Je crois que c est correct, mais je ne guarantie rien car je n ai implemente cet algorithme qu en Caml (langage au programme en math sup).

Commentaire de ZogStriP le 25/07/2004 11:49:20 administrateur CS

Le problème c'est quand c/c++ on ne peut pas retourner un tableau à deux dimensions !

Il faut le faire comme je l'ai fait !

Commentaire de Xs le 25/07/2004 13:32:05

Ah bon ? C'est la meilleure celle-là.

En C/C++, peut etre que tu ne peux pas retourner de tableau a 2 dim, mais en tout cas tu peux retourner un double ptr :

int**exponentiation_rapide(int mat[2][2], int Puissance)
{
    int **resultat // la matrice unite
    *resultat = new int[2]

for(int i=0;i<2;i++)
   resultat[i] = new int[2];

    while (Puissance != 0)
    {
        // si Puissance est impair :
        if(Puissance % 2)
            resultat = mult_mat(resultat,mat);
        mat = mult_mat(mat,mat);
        Puissance /= 2;
    }
    return resultat;
}

Commentaire de JCDjcd le 26/07/2004 19:56:40

Le nombre d'or est lie au suite de fibbonacci par la relation dite plus haut, d'ailleurs cette methode est "instantanée" du faite que sont calcul ne depend pas de n, donc => O(k) avec k une constante independante de n. Pour la demonstration, elle n'est pas tres complique.

Sinon je voudrais intervenir au sujet de l'exponentielle rapide. L'algorithme est pas si difficile a comprendre (je l'ai implementer pour une cryptage RSA pour mon TPE de premier). Le but est d'elever un nombre (au une matrice) a une exposant entier (x^n). Si vous ecrivez l'exposant en base 2, alors on s'apersoit qu'il faut mutiplier par x le nombre si il y a un 1, et sinon dans les deux autre cas (0/1) on eleve au carre.

Commentaire de coucou747 le 26/07/2004 20:01:51 administrateur CS

euh...
si je comptrends bien ,ceci devrais fonctionner pour calculer cette suite ?

#include <stdio.h>
int main(void)
{
int unsigned long a,b,c,i=1;
a=0;
b=1;
i++
c=a+b;
printf("f(%i)=%d\n",i,c);
a=b;
b=c:
}

Commentaire de coucou747 le 26/07/2004 20:04:33 administrateur CS

oups, j'avais oublié la boucle... voici la version corigée :

#include <stdio.h>
int main(void)
{
int unsigned long a,b,c,i=1;
a=0;
b=1;
while(1){
i++
c=a+b;
printf("f(%i)=%d\n",i,c);
a=b;
b=c:
}
}

Commentaire de JCDjcd le 27/07/2004 10:59:59

Non la formule suivant, temps de calcul independant de n !! :

Un=1/sqrt(5) * [p0^n - p1^n]
avec p0 et p1 les deux nombres en or :
p0=(1+sqrt(5))/2
p1=(1-sqrt(5))/2

DEMONSTRATION DE LA FORMULE :
on suppose que Un est de la forme x^n (c'est exponentielle, donc ...) alors Un+2 = Un+1 + Un
Donc : x^(n+2) - x^(n+1) - x^n = 0     <=>   x^n * [x²-x-1] = 0
On suppose que x est non nul, donc x²-x-1=0
donc x=p0 ou x=p1 (nombres definis plus haut, les deux nombres en or).
De plus on peut rajouter un constant k devant x^n : Un = k.x^n
La demonstration est la meme. Mais on a aussi : U0=0 et U1=1, c'est deux conditions nous obligent a ecrire : Un = k0.p0^n + k1.p1^n    (qui est solution de Un+2 = Un+1 + Un, voir demonstration plus haut), il suffit donc de determiner k0 et k1 selon les deux valeurs initiales de U0 et U1.
U0 = 0 = k0 + k1   donc   k1 = -k0
U1 = 1 = k0.p0 + k1.p1  donc  k0(p0-p1)=1  donc k0=1/(p0-p1)
Or p0-p1=sqrt(5) , faite le calcul vous meme ...
D'ou la formule :

Un=1/sqrt(5) * [p0^n - p1^n]

ou sinon :

Un=1/sqrt(5) * [((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n]
1

Commentaire de coucou747 le 27/07/2004 14:10:16 administrateur CS

oulala je comprends plus moi....
faut que je me recicle en bac es...
Ta solution est surement plus rapide si tu cherche un grand nombre, mais si tu cherche toute la suite, que tu veux l'enregistrer dans un fichier ?
Ce que j'ai dit marche ?
Sur ma calculatrice j'ai fais ce joli petit programme, et j'obtient
1 + f(n-1) / f(n) environ = a (1+ sqrt(5) ) / 2;
voila voila...

Commentaire de JCDjcd le 27/07/2004 14:35:29

Ouais, si tu veux toutes la suite, il faut faire la boucle, mais si tu veux un nombre de la suite en particulier (sans calculer les precedents) alors ma methode (enfin c'est pas la mienne, mais celle que j'ai ecrite et demonstrée) est plus rapide.

Commentaire de coucou747 le 27/07/2004 14:43:01 administrateur CS

ok, je ne m'ataques pas a des problèmes de math de ce niveau la si ça ne m'interesse pas vraiment (dsl de te le dire comme ça)

J'adore les math, mais pour moi, ce petit programme n'était qu'un exercice de maitrise du C (enfin, celui en tibasic, je sais pas pourquois je l'ai fait...)

je cherches en ce moment a faire du AES alors je sais c'est plus compliqué, mais en me temps on fait qqch d'un peu plus concret...

Cependant très bonne solution, mais faut y ajouter une fonction de gestion de grands nombres... (ce que je suis entrain de faire pour le rsa)

Commentaire de MetalDwarf le 27/07/2004 22:10:44

Alors la je dis FAUTE!!
Non ce programme n est pas en O(k) (d ailleurs O(k) ca se dit pas, on dit O(1) en general).
Tu crois qu une matrice ca s eleve a la puissance n comme ca?? Et non c est de la que vient la complexite. Et justement le complexite de ce programme est en O(log2(n)), et ca j en suis sur je devais le demontrer en DS d info cette annee!!

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Algorithme de compression STAR amélioré [ par hi_vivie2 ] Bonjour à tous,Je dois réaliser de manière urgente l'implémentation en java de l'algorithme de compression STAR amélioré appliqué aux images en mouvem Algorithme de compression STAR amélioré [ par hi_vivie2 ] Bonjour à tous,Je dois réaliser de manière urgente l'implémentation en java de l'algorithme de compression STAR amélioré appliqué aux images en mouvem un programme à creer [ par yoyo ] je dois creer un programme permettant d trouver les nombres premiers.l'algorithme est donné, et il utilise des tableaux dont les cases sont remplies p Qui sait l'algorithme pour calculer les racines? [ par TMT ] Aidez-moi! conversion de la partie fractionnaire en base n [ par Alucard ] J'ai vu qu'il y avait beaucoup d'algorithme de la partie entière (int) d'un nombre en n'importe quel base mais je voulais savoir si quelqu'un avait un Algorithme de mélange [ par C2S ] bonjour, j'aimerais connaitre un algorithme de mélange d'un tableau... (aléatoire) ... c'est pour simuler une fonction "mélanger" relative a un paquet aide sur l'algorithme AMR [ par semecurbep ] Votre texte iciVotre texte ICIVotre texte ICI map basic?????? [ par Sfoued2003 ] slt tout le monde,je me demande si je peux faire implémenter un algorithme de Electre1 sur map basic, pour pouvoir l'utiliser aprés sur map info? et ç algorithme de gauss et decomposition LU [ par speedamine ] bonjour a tous.je voudrai avoir des algorithmes ,ecrits en borland pascal,suivants:methode de gauss ordinaire pour la resolution d'un systeme .la deco Algorithme conversion Noms longs <-> Noms courts [ par franck406 ] Je suis à la recherche de l'algorithme qui permet d'obtenir un nom fichier court à partir d'un nom de fichier long comme le fait Dos. Je dois écrire u


Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,636 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales