/** DEBUT BIGINT addition(BIGINT, BIGINT); DEBUT **/
BIGINT addition(BIGINT nb1, BIGINT nb2) {
    BIGINT resultat;
    int tmp;
    unsigned int retenue = 0;

    initListe(&resultat);

    /// Gestion du signe du résultat ///
    if(nb1.signe == MOINS && nb2.signe == PLUS) {
        nb1.signe = PLUS;
        resultat = soustraction(nb1, nb2);
        resultat.signe = MOINS;
        return resultat;
    } else if (nb1.signe == PLUS && nb2.signe == MOINS) {
        nb2.signe = PLUS;
        return resultat = soustraction(nb1, nb2);
    } else if(nb1.signe == MOINS && nb2.signe == MOINS) {
        resultat.signe = MOINS;
        nb1.signe = PLUS;
        nb2.signe = PLUS;
    }

    while(!listeVide(nb1) && !listeVide(nb2)) {
        tmp = nb1.fin->valeur + nb2.fin->valeur + retenue;
        retenue = tmp / 10;
        empilerListe(&resultat, tmp % 10);
        nb1.fin = nb1.fin->precedent;
        nb2.fin = nb2.fin->precedent;
    }

    /// Necessaire si nb1.nbEl > nb2.nbEl, il faut finir l'addition avec le reste des chiffres de nb1.nbEl ///
    /** J'ai séparé volontairement cette condition de la boucle principale, pour éviter une condition qui n'est pas nécessaire
     ** dans le cas ou nb1.nbEl = nb2.nbEl. Cela ajoute une répétition dans l'ecriture mais un léger gain en performance
     **/
    while(!listeVide(nb1)) {
        tmp = nb1.fin->valeur + retenue;
        retenue = tmp / 10;
        empilerListe(&resultat, tmp % 10);
        nb1.fin = nb1.fin->precedent;
    }

    /// Necessaire si nb2.nbEl > nb1.nbEl, il faut finir l'addition avec le reste des chiffres de nb2.nbEl ///
    /** J'ai séparé volontairement cette condition de la boucle principale, pour éviter une condition qui n'est pas nécessaire
     ** dans le cas ou nb2.nbEl = nb1.nbEl. Cela ajoute une répétition dans l'ecriture mais un léger gain en performance
     **/
    while(!listeVide(nb2)) {
        tmp = nb2.fin->valeur + retenue;
        retenue = tmp / 10;
        empilerListe(&resultat, tmp % 10);
        nb2.fin = nb2.fin->precedent;
    }

    /// Ajout de la retenue de fin, si elle existe. Exemple 99 + 10 = 1 retenue et 09 => 109 //
    if(retenue) empilerListe(&resultat, 1);

    nettoyerNb(&resultat);

    return resultat;
}
void nettoyerNb(BIGINT *nb) {
    int out = 1;

    if(!nb->debut->valeur && nb->nbEl > 1) {
        while(out && !listeVide(*nb)) {
            if(!nb->debut->valeur) {
                depilerListe(nb);
            } else {
                out = 0;
            }
        }
        if(listeVide(*nb)) empilerListe(nb, 0);
    }
}
void afficherListe(BIGINT liste) {
    if(liste.signe == MOINS) printf("-");
    while(!listeVide(liste)) {
            printf("%d", liste.debut->valeur);
            liste.debut = liste.debut->suivant;
    }
}
void viderListe(BIGINT *ptrListe) {
    while(!listeVide(*ptrListe)) {
        depilerListe(ptrListe);
    }

    initListe(ptrListe);
}
/** DEBUT int comparer_nb(BIGINT, BIGINT); DEBUT **/
int comparer_nb(BIGINT nb1, BIGINT nb2) {
    int max = 0;

    if(nb1.signe > nb2.signe) return SUP;
    else if(nb1.signe < nb2.signe) return INF;
    if(nb1.nbEl > nb2.nbEl) return (nb1.signe) ? SUP : INF;
    else if (nb1.nbEl < nb2.nbEl) return (nb2.signe) ? INF : SUP;


    while( max == 0 && (!listeVide(nb1) && !listeVide(nb2))) {
        if(nb1.debut->valeur > nb2.debut->valeur) max = SUP;
        else if(nb1.debut->valeur < nb2.debut->valeur) max = INF;
        nb1.debut = nb1.debut->suivant;
        nb2.debut = nb2.debut->suivant;
    }

    return max;
}
// parcours inverse : du dernier vers le premier
void parcoursListeSymI (ListeS* ls, void (*f) (Objet*)) {
if (listeVide(ls)) {
printf ("Liste symétrique vide\n");
} else {
Element* ptc = dernier (ls);
while (ptc != NULL) {
f (ptc->reference);
ptc = precedent (ptc);
}
}
}
BIGINT clone(BIGINT nb) {
    BIGINT clone;

    initListe(&clone);

    while(!listeVide(nb)) {
        insererFin(&clone, nb.debut->valeur);
        nb.debut = nb.debut->suivant;
    }

    return clone;
}
// insérer "objet" en fin de la liste symétrique ls
void insererEnFinDeListeSym (ListeS* ls, Objet* objet) {
Element* nouveau = creerElement();
nouveau->reference = objet;
nouveau->suivant = NULL;
if (listeVide(ls)) { // liste symétrique vide
nouveau->precedent = NULL;
ls->premier = nouveau;
} else {
nouveau->precedent = ls->dernier;
ls->dernier->suivant = nouveau;
}
ls->dernier = nouveau;
}
 // valeur du polynôme po pour un x donné
 double valeurPolynome (Polynome* po, double x) {
     Liste* li = po;
     double resu = 0;
     if (listeVide (li) ) {
         printf ("Polynôme nul\n"); exit (1);
     } else {
         ouvrirListe (li);
         while (!finListe (li)) {
             Monome* ptc = (Monome*) objetCourant (li);
             resu += ptc->coefficient*puissance(x, ptc->exposant);
         }
     }
     return resu;
 }
/** DEBUT BIGINT divisionScolaire(BIGINT, BIGINT); DEBUT **/
BIGINT divisionScolaire(BIGINT nb1, BIGINT nb2) {
    BIGINT resultat, ligne;
    BIGINT tmp;

    initListe(&resultat);
    initListe(&ligne);

    /// Variable pour vidage mémoire des calculs intermédiaires ///
    initListe(&tmp);

    /// Gestion du signe du résultat ///
    resultat.signe = nb1.signe * nb2.signe;

    nb1.signe = PLUS;
    nb2.signe = PLUS;

    if(comparer_nb(nb1, nb2) == INF) {
        empilerListe(&resultat, 0);
        return resultat;
    } else if(comparer_nb(nb1, nb2) == EGAL) {
        empilerListe(&resultat, 1);
        return resultat;
    } else if(nb2.debut->valeur == 0 && nb2.nbEl == 1) {
        /// Impossible de diviser par zero ///
        return;
    }

    while(!listeVide(nb1)) {
        insererFin(&ligne, 0);
        ligne.fin->valeur = nb1.debut->valeur;
        insererFin(&resultat, 0);

        nettoyerNb(&ligne);

        while(comparer_nb(ligne, nb2) >= EGAL) {
            resultat.fin->valeur += 1;
            tmp = soustraction(ligne, nb2);

            viderListe(&ligne);

            ligne = tmp;
        }
        nb1.debut = nb1.debut->suivant;
    }

    nettoyerNb(&resultat);

    return resultat;
}
Beispiel #11
0
void insererFin(BIGINT *ptrListe, NOMBRE valeur) {
    CELLULE *tmp = malloc(sizeof(CELLULE));
    if(!tmp) exit(1);

    tmp->valeur = valeur;
    tmp->suivant = NULL;
    tmp->precedent = ptrListe->fin;
    if(listeVide(*ptrListe)) {
        ptrListe->debut = tmp;
    } else {
        ptrListe->fin->suivant = tmp;
    }
    ptrListe->fin = tmp;
    ptrListe->nbEl += 1;
}
/** DEBUT BIGINT multiplicationBasique(BIGINT, BIGINT); DEBUT **/
BIGINT multiplicationBasique(BIGINT nb1, BIGINT nb2) {
    BIGINT resultat, ligne, tmp;
    int j, signe_nb1, signe_nb2;

    signe_nb1 = nb1.signe;
    signe_nb2 = nb2.signe;
    nb1.signe = PLUS;
    nb2.signe = PLUS;

    initListe(&resultat);

    /// Variable pour vidage mémoire des calculs intermédiaires ///
    initListe(&tmp);

    /// Cas ou nb1 ou nb2 seraient égal à 0, on renvoie 0 directement ///
    if(egal_zero(nb1) || egal_zero(nb2)) {
        empilerListe(&resultat, 0);
        return resultat;
    }

    ligne = nb1;

    while(!listeVide(nb2)) {
        for(j = 1; j <= nb2.fin->valeur; j += 1) {
            tmp = addition(resultat, ligne);
            viderListe(&resultat);
            resultat = tmp;
        }
        nb2.fin = nb2.fin->precedent;
        insererFin(&ligne, 0);
    }

    /// Gestion du signe du résultat ///
    resultat.signe = signe_nb1 * signe_nb2;

    return resultat;
}
Beispiel #13
0
 booleen pilevide(Pile* p){
     return listeVide(p);
 }
/** DEBUT BIGINT multiplicationKaratsuba(BIGINT, BIGINT); DEBUT **/
BIGINT multiplicationKaratsuba(BIGINT nb1, BIGINT nb2) {
    BIGINT x0, x1, y0, y1, p0, p1, p2, resultat;
    BIGINT tmp, tmp2;
    int m, i, signe_nb1, signe_nb2;

    signe_nb1 = nb1.signe;
    signe_nb2 = nb2.signe;
    nb1.signe = PLUS;
    nb2.signe = PLUS;
    nb1.signe = PLUS;
    nb2.signe = PLUS;

    initListe(&resultat);

    /// Variables pour calculs intermédiaires ///
    initListe(&x0);
    initListe(&x1);
    initListe(&y0);
    initListe(&y1);
    initListe(&p0);
    initListe(&p1);
    initListe(&p2);

    /// Variables pour vidage mémoire des calculs intermédiaires ///
    initListe(&tmp);
    initListe(&tmp2);

    /// On enlève les 0 devant nb1 et nb2, car la taille du nombre est importante dans l'execution de l'algorithme de karatsuba ///
    nettoyerNb(&nb1);
    nettoyerNb(&nb2);

    /// m = milieu du plus grand nombre. Exemple : 9828839 => m = 4, 192893 => m = 3 ///
    m = (max_element(nb1, nb2) + 1) / 2;

    /// Creation de x0 et x1, dont nb1 = x1 * B^m + x0 ///
    if(nb1.nbEl <= m) {
        x0 = clone(nb1);
        empilerListe(&x1, 0);
    } else {
        for(i = 0; i < m; i += 1) {
            empilerListe(&x0, nb1.fin->valeur);
            nb1.fin = nb1.fin->precedent;
        }
        while(!listeVide(nb1)) {
            empilerListe(&x1, nb1.fin->valeur);
            nb1.fin = nb1.fin->precedent;
        }
    }

    /// Creation de y0 et y1, dont nb2 = y1 * B^m + y0 ///
    if(nb2.nbEl <= m) {
        y0 = clone(nb2);
        empilerListe(&y1, 0);
    } else {
        for(i = 0; i < m; i += 1) {
            empilerListe(&y0, nb2.fin->valeur);
            nb2.fin = nb2.fin->precedent;
        }
        while(!listeVide(nb2)) {
            empilerListe(&y1, nb2.fin->valeur);
            nb2.fin = nb2.fin->precedent;
        }
    }

    /// On enlève les 0 devant x0, x1, y0 et y1, car la taille du nombre est importante dans l'execution de l'algorithme de karatsuba ///
    nettoyerNb(&x0);
    nettoyerNb(&x1);
    nettoyerNb(&y0);
    nettoyerNb(&y1);

    /// Calculs d'après l'algorithme de karatsuba (voir description) ///
    p0 = multiplication(x0, y0);
    p2 = multiplication(x1, y1);

    tmp = addition(x0, x1);
    tmp2 = addition(y0, y1);

    p1 = multiplication(tmp, tmp2);

    viderListe(&tmp);
    viderListe(&tmp2);
    viderListe(&x0);
    viderListe(&x1);
    viderListe(&y0);
    viderListe(&y1);

    tmp = soustraction(p1, p2);

    p1 = soustraction(tmp, p0);

    viderListe(&tmp);

    puissancede10(&p1, m);
    puissancede10(&p2, (m * 2));

    tmp = addition(p0, p2);
    resultat = addition(p1, tmp);

    viderListe(&tmp);

    /// Gestion du signe du résultat ///
    resultat.signe = signe_nb1 * signe_nb2;

    return resultat;
}
/** DEBUT BIGINT soustraction(BIGINT, BIGINT); DEBUT **/
BIGINT soustraction(BIGINT nb1, BIGINT nb2) {
    BIGINT resultat;
    int tmp;
    unsigned int retenue = 0;

    initListe(&resultat);

    //nettoyerNb(&nb1);
    //nettoyerNb(&nb2);

    if(egal_zero(nb2)) return clone(nb1);
    else if(egal_zero(nb1)) {
        nb2.signe = nb2.signe * -1;
        return clone(nb2);
    }

    /// Gestion du signe du résultat ///
    if(nb1.signe == MOINS && nb2.signe == PLUS) {
        nb1.signe = PLUS;
        resultat = addition(nb1, nb2);
        resultat.signe = MOINS;
        return resultat;
    } else if(nb1.signe == PLUS && nb2.signe == MOINS) {
        nb2.signe = PLUS;
        resultat.signe = PLUS;
        return resultat = addition(nb1, nb2);
    } else if(nb1.signe == MOINS && nb2.signe == MOINS) {
        BIGINT tmp = nb1;
        nb1 = nb2;
        nb2 = tmp;
        nb2.signe = PLUS;
        nb1.signe = PLUS;
    }

    if(comparer_nb(nb1, nb2) == INF) {
        BIGINT tmp = nb1;
        nb1 = nb2;
        nb2 = tmp;
        resultat.signe = MOINS;
    }

    /// Necessaire si nb2.nbEl > nb1.nbEl, il faut finir la soustraction avec le reste des chiffres de nb2.nbEl ///
    /** J'ai séparé volontairement cette condition de la boucle principale, pour éviter une condition qui n'est pas nécessaire
     ** dans le cas ou nb2.nbEl = nb1.nbEl. Cela ajoute une répétition dans l'ecriture mais un léger gain en performance
     **/
    while(!listeVide(nb2)) {
        tmp = (nb1.fin->valeur - retenue - nb2.fin->valeur);
        if(nb1.fin->valeur > 0) retenue = 0;
        if(tmp < 0) {
            tmp = tmp + 10;
            retenue = 1;
        }
        empilerListe(&resultat, tmp % 10);
        nb1.fin = nb1.fin->precedent;
        nb2.fin = nb2.fin->precedent;
    }

    /// Necessaire si nb1.nbEl > nb2.nbEl, il faut finir la soustraction avec le reste des chiffres de nb1.nbEl ///
    /** J'ai séparé volontairement cette condition de la boucle principale, pour éviter une condition qui n'est pas nécessaire
     ** dans le cas ou nb1.nbEl = nb2.nbEl. Cela ajoute une répétition dans l'ecriture mais un léger gain en performance
     **/
    while(!listeVide(nb1)) {
        tmp = nb1.fin->valeur - retenue;
        if(nb1.fin->valeur > 0) retenue = 0;
        if(tmp < 0) {
            tmp = tmp + 10;
            retenue = 1;
        }
        empilerListe(&resultat, tmp % 10);
        nb1.fin = nb1.fin->precedent;
    }

    nettoyerNb(&resultat);

    return resultat;
}