IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Programme Fibonacci sur de grands nombres


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut Programme Fibonacci sur de grands nombres
    Bonjour,
    Ceci est mon premier message, j'espère qu'il correspondra aux normes.
    Je cherche à calculer le nième terme de la suite de Fibonacci au-delà de la taille d'un long long (64bits).
    J'utilise ainsi des tableaux d'entiers.
    Après avoir réussi à faire fonctionner le programme sur un tableau d'entier d'une taille fixée, j'essaie maintenant d'allouer/réallouer la bonne taille au cours du programme.
    Cependant j'obtiens un problème à partir d'un certain n de fib(n) ( 31 pour être exact ).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    int AddNbr (int* nbr1, int* nbr2, int base, int taille); 
    void InitNbr (int* nbr, int taille);
    void AffichNbr (int* nbr, int* taille);
    void CopyTab (int* nbr1, int* nbr2, int taille);
    int* FibGdNbr(int* nbr1, int* nbr2, int n, int* taille);
    int NbrChiffre (int n);
     
    int main(int argv, char* argc[])
    {
        int *nbr1, *nbr2;
        int n=atoi(argc[1]);
        int taille=1;
        nbr1=malloc(sizeof(int));
        nbr2=malloc(sizeof(int));
        nbr1[0]=1;
        nbr2[0]=1;
        //InitNbr(nbr1,taille);
        //InitNbr(nbr2,taille);
        AffichNbr(FibGdNbr(nbr1,nbr2,n,&taille), &taille);
        free(nbr1);
        free(nbr2);
        return EXIT_SUCCESS;
    }
     
    /*int NbrChiffre (int n) // fonction bte qui essaie de dterminer  l'avance le nombre de chiffres dans fib(n) (le problme tant qu'on ne peut pas le dterminer aprs fib(92) car impossible de stocker la valeur dans une variable)
     
    {
        int cpt=0;
        long long int nbr;
        nbr=1/sqrt(5)*((int)pow( (1+sqrt(5))/2, n) );
        while (nbr>=1)
        {
            nbr/=10;
            cpt++;
        }
        return cpt;
    }
    */
     
    int AddNbr (int* nbr1, int* nbr2, int base, int taille) // renvoie 1 si depassement
    {
        int i, ret=0;
        for (i=0; i<taille; i++)
        {
            ret=nbr1[i]+nbr2[i]+ret;
            if (ret>=base)
            {
                nbr1[i]=ret-base;
                ret=1;
            }
            else
            {
                nbr1[i]=ret;
                ret=0;
            }
        }
        return ret;
    }
     
    /*void InitNbr (int* nbr, int taille) //inutile si ma taille de tableau est de 1 seule case au dpart
    {
        int i;
        nbr[0]=1;
        for (i=1; i<taille; i++)
            nbr[i]=0;
    }
    */
     
    void AffichNbr (int* nbr, int* taille) // je passe un pointeur pour tre sr que la valeur de taille soit la mme que celle du main
    {
        int i;
        for (i=0; i<*taille; i++)
            printf("%d", nbr[(*taille)-1-i]);
        printf("\n");
    }
     
    void CopyTab (int* nbr1, int* nbr2, int taille)
    {
        int i;
        for (i=0; i<taille; i++)
            nbr1[i]=nbr2[i];
    }
     
    int* FibGdNbr(int* nbr1, int* nbr2, int n, int *taille)
    {
        int i=0;
        int* tmp=malloc((*taille)*sizeof(int));
        if(n==0 || n==1)
            return nbr1;
        else
            while(i<n-2)
            {
                CopyTab(tmp,nbr2, *taille);
                if( AddNbr(nbr2,nbr1,10,*taille) == 1 ) // si le nombre de chiffres de la somme de nbr1 et nbr2 (avec nbr2>nbr1) dpasse le nombre de cases du tableau alors
                {
                    nbr2=realloc(nbr2,*(taille)+1); // on agrandit la taille de nbr2 d'une case
                    nbr2[*taille]=1; // on applique le reste non appliqu prcdement,  cette nouvelle case
                    CopyTab(nbr1,tmp,*taille); // on copie les lments avant d'augmenter la taille de nbr1 
                    nbr1=realloc(nbr1,(*taille)+1);
                    nbr1[*taille]=0; // on met  0 la nouvelle case pour ne pas affecter la somme au prochain tour de boucle
                    tmp=realloc(tmp,(*taille)+1); // et on ajoute une case  tmp qui recevra nbr2 
                    (*taille)++;
                }
     
                else
                    CopyTab(nbr1,tmp,*taille);
                i++;
            }
            free(tmp);
            return nbr2;
    }
    et l'erreur renvoyée ( je n'ai jamais eu d'erreur de ce type auparavant, je ne saurais trop comment la régler )

    1.*** glibc detected *** ./nombre.exe: realloc(): invalid pointer: 0x00000000024b3050 ***
    2.======= Backtrace: =========
    3./lib/x86_64-linux-gnu/libc.so.6(+0x78a96)[0x7f1966f9ca96]
    4./lib/x86_64-linux-gnu/libc.so.6(realloc+0x2e6)[0x7f1966fa10d6]
    5../nombre.exe[0x400973]
    6../nombre.exe[0x4006d7]
    7./lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f1966f4530d]
    8../nombre.exe[0x4005a9]
    .......
    Tout commentaire ou critique est la bienvenue.
    Merci.

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Au lieu d'un tableau, utilise plutôt une file, ça évitera de faire des realloc en boucle et tu aura beaucoup plus d'espace mémoire
    (un tableau est un bloc de mémoire contigu)

    Ensuite rien ne vaut le précalcul.
    A chaque f(n) si le f(n) n'existe pas, enregistre la solution dans ou plusieurs fichiers
    Ainsi quand tu devrait faire un f(n+k) tu pourra repartir de f(n). Tu gagnera ainsi pas mal de temps.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Au lieu d'un tableau, utilise plutôt une file, ça évitera de faire des realloc en boucle et tu aura beaucoup plus d'espace mémoire
    (un tableau est un bloc de mémoire contigu)
    Le problème serait donc que le realloc essaie d'ajouter au tableau une case mémoire déjà allouée? Du coup le problème ne se manifesterait pas forcément à la 31ième itération de Fibonacci si je redémarrais.

    Citation Envoyé par Neckara
    Ensuite rien ne vaut le précalcul.
    A chaque f(n) si le f(n) n'existe pas, enregistre la solution dans ou plusieurs fichiers
    Ainsi quand tu devrait faire un f(n+k) tu pourra repartir de f(n). Tu gagnera ainsi pas mal de temps.
    L'accès à une fichier est plus lent qu'un accès mémoire. Cela serait compensé par la boucle qu'il faudrait faire pour atteindre le dernier élément de la liste chainée?
    N'existe-t'il donc aucun moyen d'augmenter la taille d'un tableau à l'aide d'un realloc si la case suivant la dernière case d'un tableau est déjà allouée?

  4. #4
    Membre éclairé Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Points : 790
    Points
    790
    Par défaut
    C'est une erreur au niveau d'un realloc. Tu n'en as que deux dans ton programme. Donc c'est autour de ces points qu'il faut chercher. Je suppose que tu dois aller modifier un pointeur en écrivant où il ne faut pas...

    J'ai aussi un truc qui me semble louche (mais c'est juste une impression, je n'ai pas regardé en détail), c'est que parfois tu fais des
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    alloc((*taille)*sizeof(int))
    et parfois des . Tu n'oublie pas le sizeof(int) parfois ?

    Dernière remarque, tu devrais systématiquement vérifier ce que te retourne *alloc() (bien que ton problème ne semble pas être un problème de pointeur null).

  5. #5
    Membre éclairé Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Points : 790
    Points
    790
    Par défaut
    Citation Envoyé par drogeek Voir le message
    N'existe-t'il donc aucun moyen d'augmenter la taille d'un tableau à l'aide d'un realloc si la case suivant la dernière case d'un tableau est déjà allouée?
    Mon opinion est de finir dans la voie que tu as ouvert. Accéder à un fichier et faire des listes chaînées complexifierai ton code... Et comme il n'est déjà pas clean en version "simple" ...

  6. #6
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par valefor Voir le message
    Mon opinion est de finir dans la voie que tu as ouvert. Accéder à un fichier et faire des listes chaînées complexifierai ton code... Et comme il n'est déjà pas clean en version "simple" ...
    Merci, le problème était évidement cela, l'oublie de sizeof(int) dans mes realloc. (je peux monter jusqu'à plus de f(1000) maintenant).
    Cependant votre remarque sur la propreté de mon code m'intéresse. Il faudrait que je teste la valeur renvoyée ( si elle est égale à NULL ) pour chaque *alloc.
    D'autres choses clochent?

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Une chose me chagrine :

    - FibGdNbr() peut modifier les variables locales nbr1 et nbr2 à cause des realloc().

    - AffichNbr(FibGdNbr(nbr1,nbr2,n,&taille), &taille); utilise la valeur retounée par FibGdNbr() qui est la nouvelle valeur prise par nbr1 ou nbr2 dans la fonction, donc à priori pas de problèmes.

    - Par contre, les valeurs de nbr1 et nbr2 dans main() sont inchangées et lorsqu'on fait free(nbr1); free(nbr2) on a affaire à des adresses qui sont possiblement invalides si une reallocation a déplacé les données.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par diogene Voir le message
    Une chose me chagrine :

    - FibGdNbr() peut modifier les variables locales nbr1 et nbr2 à cause des realloc().

    - Par contre, les valeurs de nbr1 et nbr2 dans main() sont inchangées et lorsqu'on fait free(nbr1); free(nbr2) on a affaire à des adresses qui sont possiblement invalides si une reallocation a déplacé les données.
    Vraiment? Le passage est pourtant par adresse, le nbr1 et nbr2 sont sensés être les mêmes dans le main et dans FibGdNbr, du coup si FibGdNbr change la valeur dans ces variables c'est sensé ne pas poser problème.
    Ou alors j'ai mal compris vos propos.

    EDIT:
    ajout de printf("%p", nbr2); dans les deux fonctions, après un certain nombre d'itérations
    l'adresse change et reste inchangée dans le main… Je ne comprends pas… nbr2=realloc est pourtant sensé stocker l'adresse renvoyée par realloc dans la variable pointée par nbr2. N'est-ce pas?

  9. #9
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Vraiment? Le passage est pourtant par adresse,...
    Il n'y a pas de passage par adresse en C, les passages sont toujours par valeur.
    le nbr1 et nbr2 sont sensés être les mêmes dans le main et dans FibGdNbr
    FibGdNbr() reçoit une copie de la valeur de nbr1 et nbr2 du main() qu'elle utilise pour initiliser les variables locales à la fonction nbr1 et nbr2.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AffichNbr(FibGdNbr(nbr1,nbr2,n,&taille), &taille);
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    Afin de pouvoir libérer la bonne portion de mémoire, j'ai bougé la déclaration de nbr1 et nbr2 dans la fonction FibGdNbr en supprimant les arguments inutiles, cependant, un problème se pose ensuite, si je souhaite libérer la mémoire avant de renvoyer la valeur de nbr2, je perds nbr2, et si je le fais après, la mémoire ne sera pas libérer (car return met fin à la fonction).
    La démarche semble donc dénuée d'intérêt.
    Faut-il donc que je crée une variable qui contiendra l'adresse de nbr2 afin que je puisse la libérer depuis le main?
    Je dois avoir l'air ridicule de buter sur des sujets aussi simples ^^'

  11. #11
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2012
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Janvier 2012
    Messages : 190
    Points : 380
    Points
    380
    Par défaut
    salut !
    je ne retire rien à ce que dit diogene.
    mais ton programme fonctionne bien. avec quelques modifs d'affichage, et une base à 1 000 000 000 (ce qui ne gaspille pas beaucoup de mémoire avec des entiers sur 32 bits) on affiche fib(1000000) en moins d'un quart d'heure sur une vieille machine.

    A+
    Don't want money. Got money. Want admiration.
    (A tribute to SSG)

  12. #12
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par anacharsis Voir le message
    salut !
    je ne retire rien à ce que dit diogene.
    mais ton programme fonctionne bien. avec quelques modifs d'affichage, et une base à 1 000 000 000 (ce qui ne gaspille pas beaucoup de mémoire avec des entiers sur 32 bits) on affiche fib(1000000) en moins d'un quart d'heure sur une vieille machine.

    A+
    Il est vrai que j'utilise 32bits pour coder des entiers < 10. Je dois gaspiller pas mal de mémoire. Merci!!

  13. #13
    Membre éclairé Avatar de valefor
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    711
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 711
    Points : 790
    Points
    790
    Par défaut
    Citation Envoyé par drogeek Voir le message
    Faut-il donc que je crée une variable qui contiendra l'adresse de nbr2 afin que je puisse la libérer depuis le main?
    Je dois avoir l'air ridicule de buter sur des sujets aussi simples ^^'
    En gardant ta structure actuelle, j’essaierai de passer ces pointeurs par adresse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void FibGdNbr(int** nbr1, int** nbr2, int n, int *taille)
    {...
    }
    Et je découperai l'appel dans le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    FibGdNbr(&nbr1,&nbr2,n,&taille)
    AffichNbr(nbr1, &taille);
    Au détail près...

  14. #14
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    J'ai mis à jour le code… je pourrais peut-être faire des tableaux de unsigned int, voir des unsigned long long int pour pouvoir augmenter d'avantage la base (bien que base 1 milliard me paraisse déjà énorme…), cela permettrait d'économiser d'avantage le nombre de cases à ajouter ( vu la contrainte de l'espace contigu des tableaux ), mais ma machine peine déjà pas mal à monter jusqu'à fibonacci de 15 000 000 ( j'en ai d'ailleurs pas vu la fin ).
    D'ailleurs, quels paramètres devrais-je considérer pour estimer le temps de calcul de ce programme selon la valeur entrée? Il y en a tellement… les boucles? Toutes? Une partie? Les conditions if ? Les calculs (addition? multiplication? Je sais qu'une multiplication prend plus de temps qu'un addition… enfin en assembleur c'était plus dur, plus complexe, et plus long en tout cas).
    Merci!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define PUISSANCE 9 // base=10^PUISSANCE
     
    int AddNbr (int* nbr1, int* nbr2, int base, int taille); 
    void InitNbr (int* nbr, int taille);
    void AffichNbr (int* nbr, int* taille);
    void CopyTab (int* nbr1, int* nbr2, int taille);
    int* FibGdNbr(int **nbr1, int **nbr2, int n, int *taille);
    int NbrChiffres (int nbr);
     
    int main(int argv, char* argc[])
    {
        int *nbr1, *nbr2;
        int n=atoi(argc[1]);
        int taille=1;
        nbr1=malloc(sizeof(int));
        nbr2=malloc(sizeof(int));
        if(nbr1 == NULL || nbr2 == NULL)
        {
            printf("Erreur à l'allocation de nbr1 ou nbr2\n");
            return EXIT_FAILURE;
        }
        nbr1[0]=1;
        nbr2[0]=1;
        AffichNbr(FibGdNbr(&nbr1,&nbr2,n,&taille), &taille);
        free(nbr1);
        free(nbr2);
        return EXIT_SUCCESS;
    }
     
    int NbrChiffres (int nbr) // retourne le nombre de chiffres contenu dans un nombre
    {
        int cpt=0;
        while (nbr>=1)
        {
            nbr/=10;
            cpt++;
        }
        return cpt;
    }
     
     
    int AddNbr (int* nbr1, int* nbr2, int base, int taille) // renvoie 1 si depassement
    {
        int i, ret=0;
        for (i=0; i<taille; i++)
        {
            ret=nbr1[i]+nbr2[i]+ret;
            if (ret>=base)
            {
                nbr1[i]=ret-base;
                ret=1;
            }
            else
            {
                nbr1[i]=ret;
                ret=0;
            }
        }
        return ret;
    }
     
    /*void InitNbr (int* nbr, int taille) //inutile si ma taille de tableau est de 1 seule case au départ
    {
        int i;
        nbr[0]=1;
        for (i=1; i<taille; i++)
            nbr[i]=0;
    }
    */
     
    void AffichNbr (int* nbr, int* taille) // Bidouillage de l'affichage pour passer de la base 10^PUISSANCE à la base 10
    {
        int i, j;
        printf("%d", nbr[(*taille)-1]);
        for (i=1; i<*taille; i++)
        {
            int NbrZeros=PUISSANCE-NbrChiffres(nbr[(*taille)-1-i]);
            for(j=0; j<NbrZeros; j++)
                printf("0");
            printf("%d", nbr[(*taille)-1-i]);
        }
        printf("\n");
    }
     
    void CopyTab (int* nbr1, int* nbr2, int taille)
    {
        int i;
        for (i=0; i<taille; i++)
            nbr1[i]=nbr2[i];
    }
     
    int* FibGdNbr(int **nbr1, int **nbr2, int n, int *taille)
    {
        int i=0;
        int* tmp=malloc((*taille)*sizeof(int));
        if(n==0 || n==1)
            return *nbr1;
        else
            while(i<n-2)
            {
                CopyTab(tmp,*nbr2, *taille);
                if( AddNbr(*nbr2,*nbr1,(int)pow(10,PUISSANCE),*taille) == 1 ) // si le nombre de chiffres de la somme de nbr1 et nbr2 (avec nbr2>nbr1) dépasse le nombre de cases du tableau alors
                {
                    *nbr2=realloc(*nbr2,(*(taille)+1)*sizeof(int)); // on agrandit la taille de nbr2 d'une case
                    if(*nbr2 == NULL)
                        printf("Erreur à la réallocation de nbr2\n"); // je ne sais pas comment arrêter le programme (un return EXIT_FAILURE ne fonctionne que dans le main)
                    else
                    {
                        (*nbr2)[*taille]=1; // on applique le reste non appliqué précédement, à cette nouvelle case
                        CopyTab(*nbr1,tmp,*taille); // on copie les éléments avant d'augmenter la taille de nbr1 
                    }
     
                    *nbr1=realloc(*nbr1,((*taille)+1)*sizeof(int));
                    if(*nbr1 == NULL)
                        printf("Erreur à la réallocation de nbr1\n");
                    else
                        (*nbr1)[*taille]=0; // on met à 0 la nouvelle case pour ne pas affecter la somme au prochain tour de boucle
                    tmp=realloc(tmp,((*taille)+1)*sizeof(int)); // et on ajoute une case à tmp qui recevra nbr2 
                    if(tmp == NULL)
                        printf("Erreur à la réallocation de tmp\n");
                    (*taille)++;
                }
     
                else
                    CopyTab(*nbr1,tmp,*taille);
                i++;
            }
            free(tmp);
            return *nbr2;
    }
    Edit: j'ai sûrement dit une bêtise… j'économise peut-être le nombre de cases à ajouter en augmentant la base, mais j'augmente aussi la taille de l'espace nécessaire pour en rajouter une, et je pourrais sûrement tomber sur un cas où l'espace restant ne serait pas assez pour 64 bits mais en revanche le serait pour 32. Du coup j'attends l'avis de quelqu'un qui a une idée plus claire sur la question ^^

  15. #15
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Tu pourrais peut être accélérer les choses en
    - utilisant un memcpy() au lieu de la fonction CopyTab()
    - réduisant le nombre de réallocations en réallouant à chaque fois que nécessaire un plus grand nombre d'int au lieu de 1 seul. Les reallocations peuvent être coûteuse si tableau est déplacé
    - évitant des déférencements inutiles (*nbr1, *nbr2) en utilisant des variables intermédiaires
    - (int)pow(10,PUISSANCE) ton compilateur peut-il calculer à la compilation cette constante ?
    ...
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  16. #16
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 18
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par diogene Voir le message
    Tu pourrais peut être accélérer les choses en
    - utilisant un memcpy() au lieu de la fonction CopyTab()
    Je ne connaissais pas, je fais un man memcpy sur le champ

    - réduisant le nombre de réallocations en réallouant à chaque fois que nécessaire un plus grand nombre d'int au lieu de 1 seul. Les reallocations peuvent être coûteuse si tableau est déplacé
    Je comprends, en effet, j'essaierai d'y remédier, mais je crains qu'il me faille changer le comportement des autres fonctions ( car j'incrémente de 1 la taille à chaque fois que je rajoute une case, et j'ai pensé tout ainsi ( je pense que c'est ma condition d'arrêt dans la plupart de mes fonctions) )
    - évitant des déférencements inutiles (*nbr1, *nbr2) en utilisant des variables intermédiaires
    Il est plus rapide de créer une nouvelle variable, y ajouter la valeur de la variable pointée par le pointeur, que d'accèder directement à la valeur de la variable pointée par le pointeur? Ca me semble étrange.

    - (int)pow(10,PUISSANCE) ton compilateur peut-il calculer à la compilation cette constante ?
    ...
    Bizarrement oui, j'utilise gcc. Je sais que la fonction pow est sensée prendre en argument des double, mais là ca fonctionne… j'imagine qu'il serait plus sage de faire un cast ici.
    Plus étrange encore, il compile et me renvoie le bon résultat alors que j'ai oublié l'option -lm.

  17. #17
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    outre ce qu'on t'a dit plus haut, tu peux encore gagner dans AddNbr :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        int i, ret=0;
        for (i=0; i<taille; i++)
        {
            ret=nbr1[i]+nbr2[i]+ret;
            if (ret>=base)
            {
                nbr1[i]=ret-base;
                ret=1;
            }
            else
            {
                nbr1[i]=ret;
                ret=0;
            }

    serait avantageusement remplacé par :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
        int i, ret=0;
        for (i=0; i<taille; i++)
        {
            ret=(*nbr1)+(*nbr2)+ret;
            if (ret>=base)
            {
                *nbr1=ret-base;
                ret=1;
            }
            else
            {
                *nbr1=ret;
                ret=0;
            }
          nbr1++ ;
          nbr2++ ;

    Au lieu de 3 calculs d'adresses, c.a.d. 3*(1 multiplication + 1 addition), tu n'aurais que 2 additions.. Tu gagnes donc à chaque boucle 3 multiplications et une addition...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

Discussions similaires

  1. Réponses: 4
    Dernier message: 05/07/2009, 16h38
  2. Réponses: 6
    Dernier message: 04/06/2008, 14h38
  3. Opération sur des grands nombres
    Par Melem dans le forum Contribuez
    Réponses: 3
    Dernier message: 11/01/2008, 13h11
  4. Modulos sur des grands nombres
    Par DjPoke dans le forum Mathématiques
    Réponses: 2
    Dernier message: 07/08/2007, 15h32
  5. requete sql sur un grand nombre d enregistrement
    Par marielaure dans le forum Langage SQL
    Réponses: 5
    Dernier message: 13/08/2004, 11h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo