Voici une proposition pour la première fonction du TP 1 :
C
#include <stdio.h> #include <stdlib.h> /** Fonction calculant la valeur absolue d'un entier */ int abs(int x) { return x >= 0 ? x : -x ; } /** Fonction calculant le max de deux entiers */ int max(int x, int y) { return x >= y ? x : y ; } /** Fonction calculant le min de deux entiers */ int min(int x, int y) { return x >= y ? y : x ; } /** Fonction renvoyant le signe d'un entier : 1 si positif, -1 si négatif, 0 si nul. */ int sgn(int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1) ; } /** Calcul du quotient et du reste de la division euclidienne "from scratch" */ void div_euc ( const int a, const int b, int qr[2] ) { if ( b == 0 ) { printf( "Division par zéro" ); exit( 1 ); } int r = a; int q = 0; while ( r < 0 || r >= abs(b) ) { q = q + sgn(r*b); r = r - sgn( r ) * abs( b ); } qr[0] = q; qr[1] = r; } /** Idem mais en "patchant" les opérateurs natifs % et / */ void div_euc2 ( const int a, const int b, int qr[2] ) { if ( b == 0 ) { printf( "Division par zéro" ); exit( 1 ); } int q = a / b ; int r = a % b ; if (a >= 0 || r == 0) { qr[0] = q; qr[1] = r; } else { qr[0] = q - sgn( b ); qr[1] = r + abs( b ); } } /** Fonction de test */ void test ( const int a, const int b ) { int qr[2] = {a,b}; div_euc(a,b,qr); printf("From scratch : %d = %d * %d + %d\n",a,b,qr[0],qr[1]); div_euc2(a,b,qr); printf("Patch : %d = %d * %d + %d\n",a,b,qr[0],qr[1]); printf("\n------------------------------\n"); } // PGCD exo 1 /** Calcul du PGCD avec l'algorithme d'Euclide */ void pgcd ( const int a, const int b, int* d ) { int aa = max(abs(a),abs(b)) ; int bb = min(abs(a),abs(b)) ; if ( aa == 0 ) { fprintf(stderr, "PGCD non défini" ); exit( 1 ); } else { int qr[2] = {aa,bb} ; while ( bb > 0 ) { div_euc (aa, bb, qr) ; aa = bb ; bb = qr[1] ; } *d = aa ; } } void testPGCD ( const int a, const int b ) { int i = 1; int* dd = &i; pgcd (a, b, dd ); printf("PGCD( %d, %d ) = %d\n", a, b, *dd); } // bezout exo 4 void bezout ( const int a, const int b, int duv[3] ) { int aa = abs( a ) ; int bb = abs( b ) ; int u = 1 ; int v = 0 ; int uu = 0 ; int vv = 1 ; int qr[2] = {aa, bb} ; while ( bb > 0 ) { div_euc (aa, bb, qr); int q = qr[0] ; int r = qr[1] ; aa = bb ; bb = r ; int utmp = u - q*uu ; u = uu ; uu = utmp ; int vtmp = v - q*vv ; v = vv ; vv = vtmp ; } duv[0] = aa ; duv[1] = sgn(a) * u ; duv[2] = sgn(b) * v; } void bzt ( const int a, const int b, int duv[3] ) { int aa = abs( a ) ; int bb = abs( b ) ; int u = 0 ; int v = 1 ; int g = bb ; int qr[2] = {0, 0} ; int r, rr, q, qq ; do { div_euc( aa, g, qr ); q = qr[0] ; r = qr[1] ; if ( r > 0 ) { g = r ; u = 1 - q * u ; v = - q * v ; } div_euc( bb, g, qr ); qq = qr[0] ; rr = qr[1] ; if ( rr > 0 ) { g = rr ; u = - qq * u ; v = 1 - qq * v ; } } while ( ( r > 0 ) || ( rr > 0 ) ) ; duv[0] = g ; duv[1] = sgn(a) * u ; duv[2] = sgn(b) * v; } void testBezout ( const int a, const int b ) { int duv[3] = {0,0,0} ; int dduv[3] = {0,0,0} ; bezout ( a, b, duv ) ; bzt ( a, b, dduv ) ; printf("Bezout : ( %d * %d ) + (%d * %d ) = %d\n", a, duv[1], b, duv[2], duv[0]); printf("Bzt : ( %d * %d ) + (%d * %d ) = %d\n", a, dduv[1], b, dduv[2], dduv[0]); printf("\n------------------------------\n"); } void inv_mod (const int n, const int x, int resultat[2] ) { int duv[3] = {0,0,0} ; bezout (x, n, duv) ; if ( n > 0 ) { int d = duv[0] ; if ( d == 1 ) { int u = duv[1]; int qr[2] = {0,0}; div_euc(u, n, qr) ; resultat[0] = qr[1] ; resultat[1] = 0 ; } else { resultat[0] = d ; resultat[1] = 1 ; } } else { resultat[0] = -1 ; resultat[1] = 2 ; } } void testInv ( const int x, const int n ) { int resultat[2] = {0,0} ; inv_mod ( x, n, resultat ) ; printf("Diagnostic : %d, u : %d \n", resultat[1], resultat[0]); printf("\n------------------------------\n"); } /////////////////////////////////////////////////////////////////// // // T P 2 // ////////////////////////////////////////////////////////////////// // Exo 1 void multi_pgcd ( const int n , int* a , int d[1] ) { pgcd ( a[0], a[1], d) ; for (int i = 2 ; i < n ; i++ ) pgcd( d[0] , a[i] , d ) ; } void testPGCDmult ( const int n, int * a ) { int d[1] = {1}; multi_pgcd (n, a, d ); printf("PGCD_mult = %d\n", d[0]); } // Exo 2 void puissance ( const int n , const int x , const int p , int z[2] ) { if ( (n > 0) && (p >= 0) ) { int qr[2] = {0 , 0} ; div_euc ( x , n , qr ) ; int tmp = qr[1] ; int pp = p ; int res = 1 ; z[1] = 0 ; while (pp > 0) { if ( pp % 2 == 0 ) { div_euc (tmp * tmp , n , qr ) ; tmp = qr[1] ; pp = pp / 2 ; } else { div_euc ( res * tmp , n , qr ) ; res = qr[1] ; pp = pp - 1 ; } } z[0] = res ; } else { if ( n <= 0 ) { fprintf(stderr, "modulo négatif\n ") ; z[1] = 1 ; } else { fprintf(stderr, "puissance négative\n ") ; z[1] = 2 ; } } } void testPower ( const int n , const int x , const int p ) { int z[2] = { 0 , 0 } ; puissance ( n , x , p , z ) ; if ( z[1] == 0 ) printf ("%d ^ %d [ %d ] = %d\n", x , p , n , z[0] ) ; } // exo 3 void affichage ( const int n , long int* x ) { printf ( "%ld" , x[n - 1] ) ; for ( int i = n - 2 ; i >= 0 ; i-- ) { printf( ":%09ld" , x[i] ); } printf("\n"); } // exo 4 int somme ( const int n , long int* x , const int p , long int* y , long int* z ) { int i ; long int t = 1000000000 ; long int ret = 0 ; long int s = 0 ; long int* nb_min ; long int* nb_max ; int t_mini ; int t_maxi ; if ( n >= p ) { nb_min = y ; nb_max = x ; t_mini = p ; t_maxi = n ; } else { nb_min = x ; nb_max = y ; t_mini = n ; t_maxi = p ; } for ( i = 0 ; i < t_mini ; i++ ) { s = nb_min[i] + nb_max[i] + ret ; z[i] = s % t ; ret = s / t ; } for ( i = t_mini; i < t_maxi ; i++ ) { s = nb_max[i] + ret ; z[i] = s % t ; ret = s / t ; } if ( ret == 0 ) { return t_maxi ; } else { z[t_maxi] = ret ; return t_maxi + 1 ; } } // exo 5 int produit ( const int n , long int* x , const int p , long int* y , long int* z ) { long int t = 1000000000 ; long int ret = 0 ; long int s = 0 ; for ( int k = 0 ; k < n + p ; k++ ) z[k] = 0 ; for ( int i = 0 ; i < n ; i++ ) { for ( int j = 0 ; j < p ; j++ ) z[i + j] += x[i] * y[j] ; } for ( int k = 0 ; k < n + p - 1; k++ ) { s = z[k] + ret ; z[k] = s % t ; ret = s / t ; } if ( ret == 0 ) { return n + p - 1 ; } else { z[n + p - 1] = ret ; return n + p ; } } int main (void) { // TP 1 /* test( 17, 3 ); */ /* test( 17, -3 ); */ /* test( -17, 3 ); */ /* test( -17, -3 ); */ /* test( 18, 3 ); */ /* test( 18, -3 ); */ /* test( -18, 3 ); */ /* test( -18, -3 ); */ /* testPGCD(17,3); */ /* testPGCD(-112,12); */ /* testPGCD(0,112); */ /* testPGCD(112,0); */ /* //testPGCD(0,0); */ /* testBezout(19,15); */ /* testBezout(-19,15); */ /* testBezout(19,-15); */ /* testBezout(19,0); */ /* testInv(5,2); */ /* testInv(-5,2); */ /* testInv(15,3); */ /* testInv(15,-3); */ /* testInv(5,0); */ /* testInv(0,5); */ // TP 2 // exo1 /* int a[5] = {18 , 15 , 27 , 36 , 72} ; */ /* testPGCDmult( 5 , a) ; */ /* int b[2] = { 27 , 36} ; */ /* testPGCDmult( 2 , b) ; */ /* int c[3] = {18 , 24, 0} ; */ /* testPGCDmult( 1 , c) ; */ // exo 2 /* testPower( 3 , 2 , 11121214 ) ; */ /* testPower( -3 , 2 , 11121214 ) ; */ /* testPower( 3 , -2 , 11121214 ) ; */ /* testPower( 3 , 2 , -11121214 ) ; */ // exo 3 /* long int x[3] = { 123456789 , 456 , -789 } ; */ /* affichage ( 3 , x ) ; */ /* long int xx[1] = { 123456789 } ; */ /* affichage ( 1 , xx ) ; */ /* // exo 4 */ long int na[5] = { 1234, 123456789 , 123456789, 123456789 , 123000000 } ; long int nb[8] = { 987654321, 987654321 , 999999999, 999999999, 999999999, 999999999, 999999999, 999999999 } ; long int ns[14] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0} ; int t = somme ( 5 , na , 8 , nb , ns ) ; printf("na = \n"); affichage( 5 , na ) ; printf("nb = \n"); affichage( 8 , nb ) ; printf("na + nb = \n"); affichage( t , ns ) ; printf("na * nb = \n"); int tt = produit ( 5 , na , 8 , nb , ns ) ; affichage( tt , ns ) ; return 0; }
On obtient par exemple:
Bash
From scratch : 17 = 3 * 5 + 2 Patch : 17 = 3 * 5 + 2 ------------------------------ From scratch : 17 = -3 * -5 + 2 Patch : 17 = -3 * -5 + 2 ------------------------------ From scratch : -17 = 3 * -6 + 1 Patch : -17 = 3 * -6 + 1 ------------------------------ From scratch : -17 = -3 * 6 + 1 Patch : -17 = -3 * 6 + 1 ------------------------------ From scratch : 18 = 3 * 6 + 0 Patch : 18 = 3 * 6 + 0 ------------------------------ From scratch : 18 = -3 * -6 + 0 Patch : 18 = -3 * -6 + 0 ------------------------------ From scratch : -18 = 3 * -6 + 0 Patch : -18 = 3 * -6 + 0 ------------------------------ From scratch : -18 = -3 * 6 + 0 Patch : -18 = -3 * 6 + 0 ------------------------------ PGCD( 17, 3 ) = 1 PGCD( -112, 12 ) = 4 PGCD( 0, 112 ) = 112 PGCD( 112, 0 ) = 112 Bezout : ( 19 * 4 ) + (15 * -5 ) = 1 Bzt : ( 19 * 19 ) + (15 * -24 ) = 1 ------------------------------ Bezout : ( -19 * -4 ) + (15 * -5 ) = 1 Bzt : ( -19 * -19 ) + (15 * -24 ) = 1 ------------------------------ Bezout : ( 19 * 4 ) + (-15 * 5 ) = 1 Bzt : ( 19 * 19 ) + (-15 * 24 ) = 1 ------------------------------ Division par zéro
Pour une compilation automatisée d'un seul fichier dans emacs avec le racourci S-z S-c :
Lisp
(defvar singleCompileC-command " gcc %s.c -o %s.out -std=c99 -Wall -Wextra -pedantic && %s.out &") (defun singleCompileC () (interactive) (save-buffer) (let ((fnse (file-name-sans-extension (buffer-file-name)))) (shell-command (format singleCompileC-command fnse fnse fnse)))) (add-hook 'c-mode-hook '(lambda nil (define-key c-mode-map [(super z) (super c)] 'singleCompileC)))
Voir cette page pour une visualisation.
Voici une documentation C faite par un camarade digne de confiance...