Voir le sujet précédent :: Voir le sujet suivant |
Auteur |
Message |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 31 Oct 2007 13:28 Sujet du message: dichotomie et récursivité |
|
|
salut, j'ai une procédure a faire.(j'ai donc du mal...).
je ne souhaite pas une solution , mais simplement des indications pour m'aider à la faire.
je dois raisonner par dichotomie pour:
résoudre une équation;pour une fonction f, résoudre f(x)=0.
on se place dans un intervalle [a,b] et on suppose que f(a) .f(b)<0.
on note x1 la solution, cad, f(x1)=0
soit c1 le milieu de l'intervalle [a,b],
si f(a).f(c1)<0 , l'intervalle [a,b] est remplacé par l'intervalle [a1,b1] = [c1,b]
si f(b).f(c1)<0 , l'intervalle [a,b] est remplacé par l'intervalle [a1,b1]=[c1,b]
On recommence l'opération en prenant c2 le milieu de l'intervalle [a1,b1].
je dois donc écrire une procédure "dichotomie" qui prend en entrée une fonction f, des points a et b, et le nombre d'itération n et qui renvoie c(n),lenombre d'itération. j'aurai ensuite à tester la procédure avec la fonction cos(x) , a=0, b=Pi , n=Pi/2.
la première chose que je ne comprends pas c'est le fait de tester la procédure avec une valeur de n définie (n=20); Le nombre d'itération n'est-il pas à déterminer au cours de la procédure? ne correspond t-il pas au nombre de fois qu'oj cherche le mileiu de l'intervalle?
j'ai fais deux tentatives de procédure (en vain):
dichotomie:=proc(f,a,b,n);
f(a);
f(b);
c:=n->(c(n-1)/2);
n:=1;
if f(a)*f(c(n))<0 then
a:=c(n);
b:=b;
elif f(b)*f(c(n))<0 then
a:=a;
b:=c(n);
else print(erreur)
fi;
if n=0 then
RETURN (a+b);
else RETURN c(n);
fi;
end:
et la deuxième :
dichotomie:=proc(f,a,b,n);
f(a);
f(b);
c(n):=(a(n)+b(n))/2;
n:=1;
while (not(c(n)=a(n)) and not(c(n)=b(n))) do
if f(a)*f(c(n))<0 then
a(n)=a(n-1);
b(n)=c(n);
elif f(b)*f(c(n))<0 then
a(n)=c(n);
b(n)=b(n-1);
else print(erreur car f(a) et f(b) ne sont pas de signe différent)
fi;
c(n+1);
od;
print (c(n));
end;
voila, je souhaiterais des indications pour me guider vers une procédure correcte (sans la solution).
Merci.. |
|
Revenir en haut de page |
|
 |
ALS
Inscrit le: 11 Sep 2006 Messages: 647
|
Posté le: 31 Oct 2007 16:55 Sujet du message: |
|
|
Bonjour, le nombre d'itérations est un entier n, et donc ne peut égaler Pi/2. A chaque étape l'intervalle a une longueur divisée par 2, soit (b-a)/2^n pour n itérations.
Le résultat à obtenir est une valeur approchée du zéro souhaité.
Tu trouveras facilement sur le Ouaibe l'algorithme decette méthode.
@+ |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 07 Nov 2007 10:07 Sujet du message: |
|
|
merci beaucoup, je vais essayer.. |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 07 Nov 2007 11:10 Sujet du message: |
|
|
Bonjour, j'ai essayé une nouvelle procédure (qui m'a l'air plutot correcte) mais le problème maintenant c'est que Maple n'arrive pas à évaluer la fonction cos(x) par exemple en certains points.
Je m'explique:
voici ma procédure:
Code: | dichotomie:=proc(f,a,b,n);
f(a);
f(b);
c(k):=(b-a)/2^k;
f(c(k));
for k from 1 to n do
if f(a)*f(k)<0 then
a:=k;
b:=b;
elif f(b)*f(k)<0 then
a:=a;
b:=k;
fi;
c(k+1);
od;
RETURN (c(n));
end: |
et quand je souhaite tester la procédure avec la fonction f(x)=cos x, a=0, b=Pi , n=20 , il y a un problème :
Code: | > dichotomie(x->cos(x),0,Pi,20);
Error, (in dichotomie) cannot determine if this expression is true or false: cos(1) < 0 |
|
|
Revenir en haut de page |
|
 |
ALS
Inscrit le: 11 Sep 2006 Messages: 647
|
Posté le: 07 Nov 2007 13:45 Sujet du message: |
|
|
Bonjour, mettre des evalf dans vos lignes de test:
if evalf(f(a)*f(k))<0 then
De plus, les instructions comme b:=k vous donneront cette erreur:
Error, (in dichotomie) illegal use of a formal parameter
car Maple interdit que l'on modifie un paramètre formel passé à une procédure. La solution consiste à copier a et b dans des variables locales a1,b1 et à travailler avec a1 et b1.
c(k) et c(k+1) ne marcheront pas non plus
A+ |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 11 Nov 2007 17:34 Sujet du message: |
|
|
bonjhour et merci pour la réponse.
j'ai suivi tes indications, mais ma procédure ne fonctionne toujours pas...
j espère finir par y arriver..lol
encore merci |
|
Revenir en haut de page |
|
 |
ALS
Inscrit le: 11 Sep 2006 Messages: 647
|
Posté le: 11 Nov 2007 19:50 Sujet du message: |
|
|
Bonsoir, voici un corrigé possible:
Code: |
> dichotomie := proc (f::procedure, a::numeric, b::numeric, eps::numeric)
local a1, b1, k, m;
a1 := a; b1 := b;
k := 0;
while eps < evalf(b1-a1) do
k := k+1; m := evalf((1/2)*a1+(1/2)*b1);
if f(m) = 0 then return m
elif f(m) < 0 then a1 := m else b1 := m
end if
end do;
print(`nombre d'itérations: ` = k, ` valeur approchée: ` = m)
end proc;
> f:=x->x^3+x-1;
3
f := x -> x + x - 1
> dichotomie(f,0,1,10^(-9));
nombre d'itérations: = 30, valeur approchée: = 0.6823278045
|
A+ |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 12 Nov 2007 22:49 Sujet du message: |
|
|
merci mais dans cette procédure, le nombre d'itérations n'est pas défini je crois.
alors que dans la mienne on entre déja un entier pour le nombre d'itérations pris en entrée dans la procédue. |
|
Revenir en haut de page |
|
 |
ALS
Inscrit le: 11 Sep 2006 Messages: 647
|
Posté le: 13 Nov 2007 8:13 Sujet du message: |
|
|
Bonjour,
oui, vous avez raison, je vous laisse adapter en suivant ce modèle, le nb d'itérations étant fourni en paramètre.
A+ |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 14 Nov 2007 13:31 Sujet du message: |
|
|
bonjour.
je crois que cette fois , c'est la bonne...
voici ma procédure:
> Code: | restart;
> dichotomie:=proc(f,a,b,n)
> local a1,b1,k,c;
> a1:=a;
> b1:=b;
> k:=(a1+b1)/2;
>
> for c from 1 to n do
> if evalf(f(a1)*f(k))<0 then
> a1:=k;
>
> elif evalf(f(b1)*f(k))<0 then
> b1:=k;
>
> fi;
>
> RETURN (evalf(k));
> od;
> end:
> dichotomie (x->cos(x),0,Pi,20);
1.570796327 |
je trouve bien Pi/2 comme zéro de la fonction, ce qui est bon signe je pense lol.
j'aimerais s'il vous plait que vous me disiez si la procédure vous parait bonne..y aurait-il quelque chose à ajouter?
merci! |
|
Revenir en haut de page |
|
 |
ALS
Inscrit le: 11 Sep 2006 Messages: 647
|
Posté le: 14 Nov 2007 13:41 Sujet du message: |
|
|
Bonjour, je pense qu'il faut mettre k:=(a1+b1)/2; à l'intérieur de la boucle for, de façon à recalculer k à chaque itération. Sinon, tout me parait correct maintenant, mis à part l'éventualité où f(k) = 0 exactement qui n'a pas été envisagée ici.
> for c from 1 to n do
> k:=(a1+b1)/2;
A+ |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 14 Nov 2007 13:46 Sujet du message: |
|
|
"l'éventualité où f(k) = 0 exactement "?
mais on a bien f(Pi/2) =0 exactement... |
|
Revenir en haut de page |
|
 |
ALS
Inscrit le: 11 Sep 2006 Messages: 647
|
Posté le: 15 Nov 2007 9:01 Sujet du message: |
|
|
Bonjour, il existe des cas où on peut tomber sur k qui vaut exactement la racine recherchée :exemple si la racine vaut 1/8 et que l'on part de 0 et 1: on aurait successivement k = 1/2, k =1/4 pour tomber sur k=1/8 donc f(k)=0 et on sort de la procédure.
A+ |
|
Revenir en haut de page |
|
 |
lyna
Inscrit le: 29 Oct 2007 Messages: 15
|
Posté le: 15 Nov 2007 9:57 Sujet du message: |
|
|
bonjour.
oui ok.
je voulais vous remercier pour toute votre aide depuis le début...
bonne journée |
|
Revenir en haut de page |
|
 |
|