/* CS 203. Correction de la feuille 2 */
/* Note : pour compiler ce fichier, il faut faire appel a la librairie mathematique avec l'option -lm */
/* Credit : certains des programmes presentes ici ont ete realises par Pierre Cohort */
#include <stdio.h>
#include <math.h> /* pour les fonctions sqrt, floor, ... */
/* exercice 1 */
double conversion(int somme_en_francs)
{
const double taux=6.55957;
return (double)somme_en_francs/taux;
/* commentaire : la syntaxe (double) devant le parametre somme_en_francs
signifie que celui-ci est, dans la division, converti en double.
La conversion est en fait ici automatique (un entier divise ou multiplie
par un reel est tjrs converti en reel). */
}
void table_franc_euro(int smin, int smax, int pas)
{
int i;
for (i=smin; i<=smax; i+=pas){
printf("%d francs = %f euros\n",i,conversion(i));
}
}
/* exercice 2 */
void table1010()
{
int i,j;
for (i=0;i<=10;i++){
for (j=0;j<=i;j++){
printf("%d * %d = %d\t",i,j,i*j);
}
printf("\n");
}
}
/* exercice 3 */
int fibonacci(int n)
{
int u0=0,u1=1,u2,i;
for (i=2;i<=n;i++){
u2=u0+u1;
u0=u1;
u1=u2;
}
return u2;
}
/* commentaire : si on desire calculer a differents moments
plusieurs valeurs de la suite, la fonction precedente n'est
pas efficace car elle induit le recalcul des premiers termes
de la suite pour chaque nouvelle valeur demandee. On peut
resoudre ce probleme en conservant en memoire le dernier indice
calcule et la valeur correspondante de u. */
int Fibonacci(int n)
{
int i;
static int u0=0,u1=1,u2,_n=2;
/* en presence du mot cle static, les initialisations precedentes
sont effectuees une seule fois (au premier appel de la fonction).
Les valeurs de u0,u1,u2 et i sont ensuite conservees en memoire
entre les differents appels a la fonction. */
for (i=_n;i<=n;i++){
u2=u0+u1;
u0=u1;
u1=u2;
}
_n=n+1;
/* la variable _n contient l'indice de depart des calculs au prochain
appel. Noter que les appels successifs a Fibonacci doivent
etres faits avec une suite croissante d'entiers. */
return u2;
}
/* exercice 4 */
/* on implemente d'abord la fonction f a partir de laquelle la
suite est definie.*/
long f(int n)
{
if (n%2==0){ /* n%2==0 equivaut a n pair */
return n/2;
} else {
return 3*n+1;
}
}
/* La fonction suivante calcule les termes d'une suite de syracuse
jusqu'a verifier la conjecture ou atteindre un indice maximal
n_max fixe a l'avance. Elle retourne min(n(u0),n_max) ou n(u0) est
le plus petit k pour lequel uk=1 */
long Syracuse(long u0)
{
const long n_max=1000000;
long u=u0,n=0;
while ((u!=1)&&(n<n_max)) {u=f(u);n++;}
return n;
}
/* teste la conjecture pour u0 dans {1,...,n} */
void Collatz(long n)
{
long i;
for (i=1;i<=n;i++){
printf("u0 = %d ; u%d = 1\n",i,Syracuse(i));
}
}
/* commentaire : il est interessant de visualiser la fonction Syracuse.
Pour cela, on ecrit une fonction qui stocke les couples (u0,Syracuse(u0))
dans un fichier. */
void writeFile(long n)
{
FILE* file=NULL;
int i;
file=fopen("syracuse.dat","w"); /* cree le fichier syracuse.dat */
if (file==NULL){ return; } /* arret si probleme d'ouverture du fichier */
for (i=1;i<=n;i++){
/* ecriture dans le fichier syracuse.dat des couples (u0,Syracuse(u0))
pour uo dans {0,...,n} */
fprintf(file,"%d %d\n",i,Syracuse(i));
}
fclose(file); /* fermeture du fichier */
}
/* Verifier que le programme a bien fonctionne en examinant
le contenu de syracuse.dat avec la commande linux
more syracuse.dat, ou en l'ouvrant avec emacs (dans ce cas, attention
a ne pas modifier le fichier). Vous pouvez visualiser les resultats graphiquement en
utilisant gnuplot (lancer gnuplot puis, sous l'invite de
commandes gnuplot, tapez plot "syracuse.dat"), ou en utilisant
matlab/scilab (en scilab : x=fscanfMat("syracuse.dat") puis
fonctions graphiques appliquees a x (voir aide du logiciel)*/
/* exercice 5 */
void racine(double a, double b, double c)
{
double delta=b*b-4*a*c;
if (delta==0.){
/* une seule racine reelle */
printf("Racine unique de %fx^2+%fx+c=0 : %f\n",a,b,c,-b/(2.*a));
} else if (delta>0) {
/* deux racines reelles */
printf("Racines de %fx^2+%fx+c=0 : %f et %f\n",
a,b,c,(-b-sqrt(delta))/(2.*a),(-b+sqrt(delta))/(2.*a) );
} else {
/* deux racines complexes conjuguees */
double r=-b/(2.*a), im=sqrt(-delta)/(2.*a);
printf("Racines de %fx^2+%fx+%f=0 : %f-i*(%f) et %f+i*(%f)\n",a,b,c,r,im,r,im);
}
}
/* exercice 6 */
/* un entier positif compris entre 10^k et 10^(k+1)-1 possede k+1 chiffres.
Donc, un entier n positif dont le logarithme en base 10 est compris entre k et k+1
(k+1 exclus) est k+1. Ainsi, le nombre de chiffres d'un entier n positif est la
partie entiere de son logarithme en base 10 plus 1. Pour les entiers negatifs, on passe
a la valeur absolue. */
int NCHIFFRES(long n)
{
if (n==0) {
return 1;
} else {
return (int)floor(log(fabs((double)(n))/log(10.)))+1;
/* en C, log est le logarithme de base e */
}
}
/* exercice 7 */
/* Le resultat du programme est l'affichage de "x=1, y=2".
Il ne s'est donc rien passe, malgre l'appel a la fonction
echange, censee echanger deux entiers.
Explication : Lors de l'appel de la fonction echange, les parametres
a et b sont temporairement crees et initialises avec les valeurs
de x et y. Ils sont ensuite echanges : apres
l'instruction b=auxi , on a bien a=2 et b=1 mais, en fin d'execution,
a et b sont detruits. Au resultat, x et y ne sont pas modifies.
Solution : il faut passer les adresses de x et y a la fonction echange, a l'aide
de pointeurs d'entiers : */
void echange(int* a, int* b)
{
int auxi;
auxi=*a;
*a=*b; /* *a est l'entier dont l'adresse est a */
*b=auxi;
}
/* L'appel a echange est alors echange(&x,&y) (&x est l'adresse de x en memoire).
La fonction echange agit ainsi directement sur les variables x et y. Le
resultat sera "x=2, y=1" */
/* exercice 8 */
/* on nomme g la fonction integree pour ne pas dupliquer l'identificateur f de
l'exercice 4 */
double g(double x)
{
return x*x;
}
double trapeze(double a, double b, double pas)
{
double h=a+pas,aux1=g(a),aux2=g(a+pas),I=0;
do {
I+=(aux1+aux2)*0.5*pas;
aux1=aux2;
h+=pas;
aux2=g(h);
} while (h<b);
return I;
}
/* exercice 9 */
float Celcius2Fahrenheit (float DegresCelcius)
/* Conversion de Degres Celcius en Degres Fahrenheit
ENTREE : DegresCelcius, temperature a convertir
SORTIE : temperature convertie en Degres Fahrenheit
*/
{
return(9.0*DegresCelcius/5.0+32);
}
float Fahrenheit2Celcius (float DegresFahrenheit)
/* Conversion de Degres Fahrenheit en Degres Celcius
ENTREE : DegreFahrenheit, temperature a convertir
SORTIE : temperature convertie en Degres Celcius
*/
{
return(5.0/9.0*(DegresFahrenheit-32));
}
int main()
{
printf("Exercice 1 :\n");
table_franc_euro(0, 100, 5);
printf("Exercice 2 :\n");
table1010();
printf("Exercice 3 :\n");
printf("fibonacci(12) = %d\n",fibonacci(12));
printf("Fibonacci(1) = %d\n",Fibonacci(1));
printf("Fibonacci(4) = %d\n",Fibonacci(4));
printf("Fibonacci(10) = %d\n",Fibonacci(10));
printf("Fibonacci(12) = %d\n",Fibonacci(12));
printf("Exercice 4 :\n");
Collatz(1000);
/*writeFile(1000);*/
printf("Exercice 5 :\n");
racine(1,1,1);
printf("Exercice 6 :\n");
printf("%d possede %d chiffres\n",124573,NCHIFFRES(124573));
printf("Exercice 7 :\n");
{
int a=1,b=2;
printf("a=%d b=%d\n",a,b);
echange(&a,&b); /* &a est l'adresse de la variable a */
printf("a=%d b=%d\n",a,b);
}
printf("Exercice 8 :\n");
{
double a=1.0,b=2.0;
printf("valeur theorique de l'integrale de g entre %f et %f = %f\n",a,b,(b*b*b-a*a*a)/3.);
printf("valeur calculee de l'integrale de g entre %f et %f = %f\n",a,b,trapeze(a,b,0.001));
}
printf("Exercice 9 :\n");
printf("20 degres Celcius corresponded a %f degres Fahrenheit\n",Celcius2Fahrenheit(20));
printf("-40 degres Fahrenheit corresponded a %f degres Celcius\n",Fahrenheit2Celcius(-40));
return(0);
}