Article View: fr.comp.lang.c
Article #15415Re: virgule flottante et FLT_EPSILON
From: Antoine Leca
Date: Tue, 27 Sep 2005 09:30
Date: Tue, 27 Sep 2005 09:30
113 lines
5886 bytes
5886 bytes
En <news:43386482$0$26880$626a14ce@news.free.fr>,
Julien � Tribulations Parall�les � va escriure:
> En effet, en essayant le petit programme ci-dessous, on se rend
> compte que x=15, y=14.
[ Les questions sont report�es plus bas ]
Pas forc�ment.
> int main(void) {
> float t2=1.5, t1=0.0, h=0.1;
Trois variables. En supposant une impl�mentation des flottants en binaire
(le plus courant, le cas base 16 est similaire, et en base 10 il n'y a pas
de probl�mes apparents), t2 et t1 sont des nombres exacts, mais h est un
rationel (mal repr�sent�, exactement comme 1/3 en d�cimal, car 5 n'est pas
un diviseur de 2).
> int x=(1.5-0.0)/0.1;
� droite du =, on a une expression en double ; 1.5-0.0 va valoir 1.5 sur
toutes les impl�mentations, mais la division suivante par le nombre rationel
0.1+e (o� e est inf�rieur en valeur absolue � l'epsilon des double rapport�
� 0.1, mais non nul) va donner un r�sultat proche de 15 mais �ventuellement
diff�rent (et selon les arrondis cela peut �tre inf�rieur ou sup�rieur ou
�gal � 15).
Ensuite on applique l'op�rateur = qui fait une conversion vers un entier,
donc arrondi par d�faut (vers 0) ; on peut trouver suivant les
impl�mentations 14 ou 15 dans x.
> int y=(t2-t1)/h;
� droite du =, on a des floats, que le compilateur peut _�ventuellement_
calculer avec une pr�cision inf�rieure. Les m�mes explications s'appliquent,
mais la valeur de h est maintenant 0.1+f, o� f est inf�rieur en valeur
absolue � l'epsilon des float rapport� � 0.1 (donc plus grand que le e
ci-dessus).
L� encore, le r�sultat sera de l'ordre de 15, selon les arrondis, inf�rieur
ou sup�rieur ou �gal � 15. Parce que � l'erreur � sur h est plus grande,
l'intervalle des valeurs possibles est plus important, donc dans les faits
tu peux avoir une plus grande variabilit�.
Ensuite m�me processus, conversion en entier donc arrondi par d�faut et on
se retrouve avec 14 ou 15.
> int y_corrected=(t2-t1+FLT_EPSILON)/h;
M�me principe. Tu ajoute une petite quantit� ce qui force g�n�ralement le
r�sultat � remonter au-dessus de 15, mais le terme de seconde ordre (au
maximum, h vaut 0.1+FLT_EPSILON*10) doit permettre � certains cas rares
d'�tre en dessous de 15.0 (enfin, je n'ai pas pos� l'�quation, il faut bien
que tu fasses quelque chose ;-)).
> Afin de r�ellement obtenir 15,
Si tu veux _r�ellement_ obtenir 15, arr�tes d'utiliser des flottants et
passe � un autre syst�me de num�ration, virgule fixe ou bignums. Les
flottants sont un moyen rapide d'obtenir des r�sultats num�riques, ce ne
sont pas des concepts math�matiques fiables.
> 1- x et y me semblent identiques au premier abord.
� chaque fois que tu vois une constante ou une variable flottante, au lieu
de penser avec des nombres r�els en t�te (cela vaut 1.5 ou 0.1), pense que
cela repr�sente un intervalle de valeurs.
> Que se passe-t-il de diff�rent dans ces deux cas?
L'amplitude de l'intervalle des float est plus grande que celle des double.
> Pourquoi passer par des noms de variable semble changer la donne?
Parce que tu as typ� tes variables.
Si tu supprimes tes variables, tu as �crit
int x=(1.5 -0.0 )/0.1;
int y=(1.5f-0.0f)/0.1f;
Penses-tu toujours que c'est identique...
> 2- Quelle d�marche employer pour obtenir la bonne valeur?
Ne pas utiliser les flottants (et encore moins les convertir en entiers).
> Rajouter au num�rateur FLT_EPSILON comme je l'ai fait constitue-t-il une
bonne solution?
Non, c'est un empl�tre sur une jambe de bois. En plus, je ne suis pas s�r
que ce soit suffisant (cf. supra) : il faudrait calculer l'epsilon global de
l'expression (la largeur de l'intervalle du r�sultat), qui d�pend
compl�tement des expressions.
Le conseil de rajouter 0.5 avant de convertir en entier te permet d'�chapper
aux probl�mes d'arrondi aux limites (ceux que tu rencontres ici), en for�ant
l'utilisation d'un arrondi � normal � (� l'entier le plus proche) plut�t que
l'arrondi par d�faut (pour les nombres positifs) utilis� normalement en C :
ici, c'est un marteau pilon pour �craser une mouche, mais au moins cela te
permet de faire des calculs approximatifs en flottants et d'obtenir un
r�sultat entier (tant que tu ne d�passes pas la capacit� de la mantisse, et
en faisant attention � ajouter 0.5 pour les valeurs sup�rieures � 0.5 mais �
le soustraire pour celles qui sont inf�rieures � -0.5), quand tu sais que
c'est cela que tu cherches.
Antoine
Technical Details
Message-ID:
<dhb3er$dg7$1@shakotay.alphanet.ch>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!news.glorb.com!news.cs.univ-paris8.fr!proxad.net!freenix!news.alphanet.ch!alphanet.ch!not-for-mailReferences:
<43386482$0$26880$626a14ce@news.free.fr>Show Full Headers
Complete Article Headers
X-Google-Thread: f9822,309c5052b3bcc1bf X-Google-Attributes: gidf9822,public X-Google-Language: FRENCH,ASCII Path: arc1-ca.pugleaf.net!g2news1.google.com!news3.google.com!news.glorb.com!news.cs.univ-paris8.fr!proxad.net!freenix!news.alphanet.ch!alphanet.ch!not-for-mail From: "Antoine Leca" <root@localhost.invalid> Newsgroups: fr.comp.lang.c Subject: Re: virgule flottante et FLT_EPSILON Date: Tue, 27 Sep 2005 11:30:01 +0200 Organization: Posted through ALPHANET (http://www.alphanet.ch/) Lines: 114 Sender: antoinel@143.red-217-127-250.staticip.rima-tde.net Message-ID: <dhb3er$dg7$1@shakotay.alphanet.ch> References: <43386482$0$26880$626a14ce@news.free.fr> NNTP-Posting-Host: 143.red-217-127-250.staticip.rima-tde.net Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit X-Trace: shakotay.alphanet.ch 1127813403 13831 217.127.250.143 (27 Sep 2005 09:30:03 GMT) X-Complaints-To: usenet@alphanet.ch NNTP-Posting-Date: Tue, 27 Sep 2005 09:30:03 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1506 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1506