Vous êtes sur la page 1sur 10

Numéro d’anonymat : 1 2013-03-25 10 :17 :18.

000000000

Reportez votre numéro d’anonymat dans le cadre ci-dessous et en haut à gauche de chaque page de
l’énoncé.

A la fin de l’épreuve glissez ce cahier dans la copie double qui vous a été fournie, qui comporte votre
numéro d’anonymat et sur laquelle vous aurez écrit et masqué votre nom en rabattant dessus et en
collant la languette triangulaire. Vous ne devez rien écrire d’autre sur cette copie double.

Numéro d’anonymat :

UNIVERSITÉ DE PARIS SUD Centre d’Orsay 2012-2013 première session d’examen

L3 et Magistère 1ère année de Physique fondamentale

Examen d’informatique 18 Mars 2013 10h à 12h bât. 337 salle 3

Aucun document n’est autorisé.


Les programmes doivent être écrits en C/C++. Les réponses doivent obligatoirement être écrites sur les feuilles de
l’énoncé, dans l’espace réservé. Il est fortement conseillé de rédiger d’abord le plan des réponses au brouillon.
Respecter les notations de l’énoncé : par exemple la variable notée nt dans l’énoncé devra être écrite nt dans un pro-
gramme, n′′ devra être écrite ns.
Ne pas commencer à répondre à un exercice avant de l’avoir entièrement lu.
L’utilisation de fonctions est laissée à l’appréciation de l’étudiant, sauf quelques cas où elle est imposée.
On suppose que tous les #include<stdlib.h> ... #include<bibli fonctions.h> using namespace std ; nécessaires
sont sous-entendus, il n’y a pas à les écrire.
On rappelle qu’on ouvre un fichier en écriture par l’instruction : fstream xxx("nom de fichier.qqc",ios : :out) ;
et en lecture par : fstream yyy("nom de fichier.qqc",ios : :in) ;
Ne pas faire lire les données au clavier ou dans un fichier par un cin >>, ou l’équivalent pour un fichier, sauf si cela est
explicitement demandé. Par défaut, les données seront donc fournies dans le programme lui-même, par des instructions
du type :
dx=0.01;
a=1.7; b=1.1;
etc.
Dans chaque exercice on suppose que le programme principal1 et les fonctions2 sont écrits dans un unique fichier.
Les exercices sont indépendants les uns des autres.
Le nombre d’étoiles (de zéro à trois) donne une indication sur le niveau de l’exercice.
Le nombre de points (sur 40) attribué à chaque exercice est indiqué entre parenthèses après le nom de l’exercice (c’est
un barème indicatif ). Deux points sont réservés à la qualité de la présentation.
A titre indicatif le nombre de lignes du corrigé de chaque exercice est indiqué entre crochets (tout compris, c’est à dire
avec int main(), les accolades, return 0 ;, des commentaires éventuels).
Le corrigé pourra être consulté sur le site du cours.

1 S’il y en a un.
2 S’il y en a.

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 2 2013-03-25 10 :17 :18.000000000

Factorisation en nombres premiers ** (9) [17 lignes]


On considère uniquement des nombres entiers positifs ou nuls.
Un nombre est premier s’il n’est divisible que par deux nombres distincts : 1 et lui-même. 1 n’est donc pas premier.
Tout nombre entier supérieur ou égal à 2 s’écrit de façon unique comme produit de nombres premiers, un même facteur
premier pouvant éventuellement être répété.
Question
Écrire un programme qui affiche la factorisation en nombres premiers de tous les nombres entiers n tels que
2 ≤ n ≤ N , de façon à obtenir une liste de la sorte :
2 : 2
3 : 3
4 : 2 2
5 : 5
6 : 2 3
7 : 7
8 : 2 2 2
9 : 3 3
10 : 2 5
11 : 11
12 : 2 2 3
13 : 13
...
On rappelle que le reste de la division de l’entier a par l’entier b s’obtient en C par a%b.
Réponse à la question :
int main()
{
int N,n,nn,i,k,ind;
cout << "N="; cin >> N;
int *p=(int *)malloc(N*sizeof(int)); // le tableau p contient la liste des nombres premiers
// (on pourrait se contenter d’un tableau statique)
p[0]=2; k=0; // au départ cette liste est réduite à un seul élément : 2
for(n=2;n<=N;n++)
{
cout << n << " : ";
ind=0; // si ind reste égal à 0 c’est que n est premier
//nn=n; // peut en fait ^etre mis ici
for(i=0;i<=k;i++)
{
nn=n; // pas nécessaire de le mettre dans la boucle
// la boucle while permet de tenir compte de la multiplicité éventuelle des facteurs
while (nn%p[i]==0) {cout << p[i] << " "; ind=1; nn=nn/p[i];}
}
if(ind==0) {k++; p[k]=n; cout << n; } // on ajoute n à la liste des nombres premiers
cout << endl;
}
return 0;
}

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 3 2013-03-25 10 :17 :18.000000000

Autre solution, plus élégante car n’utilisant pas de tableau, mais nécessitant une petite justification mathématique :
int main(){
int N, i, j, k;
N = 1000;
for (j = 2; j <= N; j++){
i = 2;
cout << j << " : ";
k = j;
while (i <= j){
if (k % i == 0){
cout << i << " ";
k = k / i;
}
else
i++;
}
cout << endl;
}
return 0;
}

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 4 2013-03-25 10 :17 :18.000000000

Pointeurs ** (11)
Dans les programmes qui suivent les flèches <------ signalent les lignes qui diffèrent.
Pour chacun de ces programmes indiquer s’il est valide, si non pourquoi, et si oui, le résultat affiché à l’écran.
Question 1
#include<iostream> #include<iostream> #include<iostream>
#include<stdlib.h> #include<stdlib.h> #include<stdlib.h>
using namespace std; using namespace std; using namespace std;
int main() int main() int main()
{ { {
int i,*p; int i,*p; int i,*p;
i=3; *p=i; i=3; p=&i; *p=3; i=*p; <------
cout << i << " " << *p << endl; cout << i << " " << *p << endl; cout << i << " " << *p << endl;
return 0; return 0; return 0;
} } }

Réponse : Réponse : Réponse :

Non valide : Valide : Non valide :


p non initialisé par une adresse. 33 p non initialisé par une adresse.

Question 2
#include<iostream> #include<iostream> #include<iostream>
#include<stdlib.h> #include<stdlib.h> #include<stdlib.h>
using namespace std; using namespace std; using namespace std;
void ff(int *p) void ff(int *p) void ff(int *p)
{ { {
cout << *p << endl; cout << *p << endl; cout << p << endl; <------
} } }
int main() int main() int main()
{ { {
int i; int i; int i;
i=5; i=5; i=5;
ff(i); ff(&i); ff(&i); <------
return 0; return 0; return 0;
} } }

Réponse : Réponse : Réponse :

Non valide : Valide : Valide :


l’argument de ff est un pointeur 5 0x7fff4d21f6dc, par exemple
qui doit recevoir une adresse et c’est l’adresse de i en
non un entier. hexadécimal.

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 5 2013-03-25 10 :17 :18.000000000

Question 3
#include<iostream> #include<iostream> #include<iostream>
#include<stdlib.h> #include<stdlib.h> #include<stdlib.h>
using namespace std; using namespace std; using namespace std;
void ff(int i) void ff(int i) void ff(int i)
{ { {
cout << i << endl; cout << i << endl; cout << i << endl;
} } }
int main() int main() int main()
{ { {
int j,*p; int j,*p; int j,*p;
p=&j; p=&j; p=&j;
j=5; j=5; j=5;
ff(j); ff(*p); ff(p); <------
return 0; return 0; return 0;
} } }

Réponse : Réponse : Réponse :

Valide : Valide : Non valide :


5 5 l’argument de ff est un entier
pointeur non utilisé. qui ne peut recevoir l’adresse
contenue dans p.

Question 4
#include<iostream> #include<iostream>
#include<stdlib.h> #include<stdlib.h>
using namespace std; using namespace std;
int main() int main()
{ {
int i,n=5; int i,n=5;
double *t=(double *)malloc(n*sizeof(double)); double *t=(double *)malloc(n*sizeof(double));
double *p; <------
for(i=0;i<n;i++) t[i]=1; for(p=t;p<t+n;p++) *p=1; <------
for(i=0;i<n;i++) cout << t[i] << " "; for(i=0;i<n;i++) cout << t[i] << " ";
cout << endl; cout << endl;
return 0; return 0;
} }

Réponse : Réponse :

Valide : Valide :
11111 11111
on peut ajouter, retrancher un entier à un pointeur et faire
des comparaisons entre pointeurs du même type.

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 6 2013-03-25 10 :17 :18.000000000

Terre inhomogène *** (12) [41 lignes]


On suppose que la Terre est sphérique et qu’elle présente une inhomogénéité de masse volumique dans une région elle-
même de forme sphérique mais décentrée.
Elle est considérée comme immobile et sans mouvement de rotation, elle a un rayon rt et une masse volumique ρ.
Un repère (O ~i ~j) a son origine au centre de la Terre.
La région d’inhomogénéité est centrée au point de coordonnées (xc , 0), elle a un rayon rc et une masse volumique αρ (α
réel ≥ 0).

~v0

~j C S
O ~i xc rt + h x

Masse volumique de la Terre dans la région figurée en blanc : ρ


Masse volumique de la Terre dans la région figurée en grisé : αρ

Un satellite est lancé avec une vitesse orthoradiale ~v0 contenue dans le plan (0xy), depuis le point de coordonnées (rt +h, 0).
L’orbite du satellite est donc contenue dans le plan (0xy). Le module de ~v0 est tel r que, si la masse volumique de la Terre
GM
était homogène (α = 1), le satellite aurait une orbite circulaire, on a donc v0 = , avec, en unités SI :
rt + h
G = 6.67 10−11 constante de la gravitation universelle
M masse de la Terre homogène
rt = 6.4 106 , rayon de la Terre
h = 8 105 altitude initiale du satellite
ρ = 5517 masse volumique de la région de la Terre figurée en blanc.
α=0
xc = 5.5 106
rc = 5 105

La Terre exerce sur le satellite une accélération :


−→ −→ !
4πρG SO SC
rt3 3
3
+ rc (α − 1)
3 SO SC 3

Question 1
Écrire un programme qui calcule la position du satellite par la méthode d’Euler3 à n instants depuis l’instant
3 En pratique il faut faire ces calculs avec la méthode de Runge-Kutta d’ordre 4 (qui n’est pas demandée ici pour simplifier l’énoncé) et non

avec celle d’Euler.

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 7 2013-03-25 10 :17 :18.000000000

2π(rt + h)
initial t = 0 jusqu’à l’instant final t = 10 T , T = étant la période du satellite dans le cas où la
v0
Terre est homogène.
x et y étant les coordonnées du satellite, les triplets t x y seront écrits dans un fichier avec un triplet par ligne.
On n’écrira pas les instructions de tracé par gnuplot.
Le programme peut-être écrit avec ou sans tableaux et avec ou sans fonctions, mais la brièveté et la lisibilité
seront appréciées.
Réponse à la question :
Version minimaliste :
int main()
{
int i,np=10000000;
double rho,alpha,rt,rt3,hh,xc,rc,rc3,G,M,c,beta,t,dt,tfin,dt3,dc3,T,x,y,vx,vy,vxp,vyp;
rho=5517; alpha=0; rt=6.4e6; rt3=rt*rt*rt; hh=8.e5; xc=5.5e6; rc=5e5; rc3=rc*rc*rc; G=6.67e-11;
M=4./3*M_PI*rt3*rho; c=1.5; beta=4*M_PI*rho*G/3;
x=rt+hh; y=0; vx=0; vy=sqrt(G*M/x); // conditions initiales
T=2*M_PI*x/vy; tfin=10*T; dt=tfin/(np-1);
fstream res("satellite.res",ios::out);
for(i=0;i<np;i++)
{
t=i*dt;
res << t << " " << x << " " << y << endl;
dt3=pow(x*x+y*y,c);
dc3=pow((x-xc)*(x-xc)+y*y,c);
vxp=-rt3*x/dt3+rc3*(alpha-1)*(xc-x)/dc3; vxp*=beta;
vyp=-rt3*y/dt3-rc3*(alpha-1)*y/dc3; vyp*=beta;
x=x+vx*dt;
y=y+vy*dt;
vx=vx+vxp*dt;
vy=vy+vyp*dt;
}
return 0;
}
Version plus structurée, avec fonctions. Dans cette version il suffit de remplacer la ligne euler(sd,q,t,dt,n) ; par
rk4(sd,q,t,dt,n) ; pour faire le calcul avec la méthode de Runge-Kutta d’ordre 4 en utilisant la fonction rk4 de la
bibliothèque des fonctions du Magistère. Tous les intermédiaires sont possibles entre cette version structurée et la version
mininimaliste ci-dessus.
double mu_,xc_,rt3_,a3_;
//***********************************************************************************************************
void sd(double *q,double t,double *qp,int n)
{
static double c=1.5; double so3,sc3;
qp[0]=q[2];
qp[1]=q[3];
so3=pow(q[0]*q[0]+q[1]*q[1],c);
sc3=pow((q[0]-xc_)*(q[0]-xc_)+q[1]*q[1],c);
qp[2]=-rt3_*q[0]/so3+a3_*(xc_-q[0])/sc3; qp[2]=mu_*qp[2];
qp[3]=-rt3_*q[1]/so3-a3_*q[1]/sc3; qp[3]=mu_*qp[3];
}
//***********************************************************************************************************
void euler(void (*eq)(double *,double,double *,int),double *q,double t,double dt,int n)
{
int i;
double *qp=(double *)malloc(n*sizeof(double));

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 8 2013-03-25 10 :17 :18.000000000

eq(q,t,qp,n);
for(i=0;i<n;i++) q[i]=q[i]+dt*qp[i];
}
//***********************************************************************************************************
int main()
{
int n=4,i,np=1000000;
double rho,alpha,rt,hh,rc,G,M,T,t,dt,tfin,*q=D_1(n);
rho=5517.; alpha=0; rt=6.4e6; hh=8.e5; rc=5e5; G=6.67e-11;
mu_=4*M_PI*rho*G/3; xc_=5.5e6; rt3_=rt*rt*rt; a3_=rc*rc*rc*(alpha-1);
M=4./3*M_PI*rt3_*rho;
q[0]=rt+hh; q[1]=0; q[2]=0; q[3]=sqrt(G*M/q[0]); // conditions initiales
T=2*M_PI*q[0]/q[3]; tfin=10*T; dt=tfin/(np-1);
fstream res("satellite.res",ios::out);
for(i=0;i<np;i++)
{
t=i*dt;
res << q[0] << " " << q[1] << endl;
euler(sd,q,t,dt,n);
//rk4(sd,q,t,dt,n);
}
return 0;
}
Question 2
Si la Terre inhomogène tournait autour d’un axe perpendiculaire au plan Oxy, comment suffirait-il de modifier
le programme ? L’indiquer en une phrase, sans écrire les instructions.
Réponse à la question :
Dans le calcul des composantes de l’accélération du satellite il suffit de remplacer les coordonnées du centre de la Terre
et du centre de la sphère hétérogène de rayon rc par leur expression en fonction du temps, connue à priori.

Champ de gravitation d’un plateau rocheux ** (8) [44 lignes]


On assimile un plateau rocheux à un parallélépipède rectangle dont les côtés ont pour longueurs lx , ly , lz .

−→ M
d3 g ×

lz
O P× y

lx
x ly

Le champ de gravitation créé par ce plateau en un point M quelconque de l’espace, de coordonnées (u, v, w), est donné
par l’intégrale :
Z lx Z ly Z lz −−→

→ MP
g (M ) = Gρ dx dy dz
0 0 0 M P3
P étant un point dont les coordonnées sont notées (x, y, z) et qui décrit tout le parallélépipède.

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 9 2013-03-25 10 :17 :18.000000000

G = 6.67 10−11 SI, est la constante de la gravitation universelle.


ρ = 5500 SI est la masse volumique du plateau supposé homogène.
M P 3 est le cube de la longueur du segment M P .
Cette intégrale peut être approchée par la somme finie sur un réseau de n × n × n points :
n X n Xn −−→
X M P ijk
G ρ δx δy δz 3
i=1 j=1
M Pijk
k=1

lx ly lz
, δy = , δz = , le point Pijk ayant pour coordonnées (i − 21 )δx , (j − 21 )δy , (k − 21 )δz .

avec : δx =
n n n
Pour la suite il est conseillé de ne pas utiliser de tableaux et d’utiliser des variables intermédiaires.
Question 1
Écrire une fonction ayant six arguments x, y, z, u, v, w et qui retourne la valeur de M P 3 .

Réponse à la question :
double ff(double x,double y,double z,double u,double v,double w)
{
double d2,cc=3./2;
d2=(x-u)*(x-u)+(y-v)*(y-v)+(z-w)*(z-w);
return pow(d2,cc);
}
Question 2
Écrire un programme qui calcule les composantes gx , gy , gz du champ de gravitation en M .

Réponse à la question :
int main()
{
int i,j,k,q,n=100,N=1000000000;
double x,y,z,dx,dy,dz,lx,ly,lz,G,rho,u,v,w,gx,gy,gz,dd,c;
G=6.67e-11; rho=5500;
lx=50e3; ly=100e3; lz=3e3;
u=25e3; v=-1e3; w=0;
// Méthode par réseau régulier
dx=lx/n; dy=ly/n; dz=lz/n;
gx=0; gy=0; gz=0;
for(i=1;i<=n;i++)
{
x=(i-0.5)*dx;
for(j=1;j<=n;j++)
{
y=(j-0.5)*dy;
for(k=1;k<=n;k++)
{
z=(k-0.5)*dz;
dd=ff(x,y,z,u,v,w);
gx+=(x-u)/dd; gy+=(y-v)/dd; gz+=(z-w)/dd;
}
}
}
c=G*rho*dx*dy*dz;
gx*=c; gy*=c; gz*=c;
cout << gx << " " << gy << " " << gz << " " << sqrt(gx*gx+gy*gy+gz*gz) << endl;
return 0;
}

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session
Numéro d’anonymat : 10 2013-03-25 10 :17 :18.000000000

Question 3
Une autre façon de calculer l’intégrale est d’utiliser l’expression :
N −−→
lx ly lz X M P q

N q=1 M Pq3

les N points Pq étant tirés aléatoirement de façon uniforme dans le parallélépipède.


Écrire un complément au programme précédent pour qu’il calcule aussi l’intégrale par cette méthode de tirages.
Réponse à la question :
Il faut ajouter à la fin du programme de la Question 2, juste avant le return 0 ;, les lignes suivantes :
// Méthode par tirages
gx=0; gy=0; gz=0;
for(q=1;q<=N;q++)
{
x=lx*drand48(); y=ly*drand48(); z=lz*drand48();
dd=ff(x,y,z,u,v,w);
gx+=(x-u)/dd; gy+=(y-v)/dd; gz+=(z-w)/dd;
}
c=G*rho*lx*ly*lz/N;
gx*=c; gy*=c; gz*=c;
cout << gx << " " << gy << " " << gz << " " << sqrt(gx*gx+gy*gy+gz*gz) << endl;

Licence et Magistère 1ère année de Physique fondamentale Examen d’informatique 2012-2013 première session

Vous aimerez peut-être aussi