OVH Cloud OVH Cloud

comparaison de flottants

209 réponses
Avatar
Emmanuel
bonjour tout le monde,

une question de vrai débutant :

Avec le programme essai.c suivant

int main(void) {
return ((1.7 + 0.1) == 1.8) ? 1 : 0;
}

j'obtiens :

$ gcc -Wall -o essai essai.c; ./essai; echo $?
1

Avec le programme essai.c suivant

int main(void) {
float x;
x = 1.7;
return ((x + 0.1) == 1.8) ? 1 : 0;
}

j'obtiens :

$ gcc -Wall -o essai essai.c; ./essai; echo $?
0

Pourtant, le programme

#include <stdio.h>
int main(void) {
float x;
x = 1.7;
printf("%f et %f\n", 1.7 + 0.1, x + 0.1);
}

affiche :
1.800000 et 1.800000

Apparremment, 1.7+0.1 et x+0.1 sont égaux ; j'imagine qu'il s'agit d'un
problème de représentation des flottants en machine mais j'aimerais bien
avoir une confirmation ou une infirmation (et une explication, si possible).

Merci par avance.

Emmanuel

10 réponses

Avatar
Vincent Lefevre
Dans l'article <4bb85991$0$30018$,
Samuel DEVULDER écrit:

Vincent Lefevre a écrit :
> Ici, on écrit du C portable. Ou alors on précise l'architecture

Non: on répond à la question du poster originel surtout!



Oui, et en l'occurrence l'OP n'a pas précisé son archi,
donc ton code (non portable) ne fonctionne pas forcément
sur sa machine! Et en tout cas pas sur nombre de machines
modernes.

Tu n'a pas compris. Je pourrais comprendre que tu fais semblant d'être
bête, mais c'est peut-être autre chose. Je répète: les compilos (et leur
bibliothèques) sont ciblés pour une machine donnée. Misra-c ne regarde
que le code qui est destiné à être portable: le code utilisateur dont
les types *ne doivent pas* utiliser les types "de base".



Tu n'as rien compris au C. Utiliser les types de base permet
d'être portable, contrairement à des types définis par telle
ou telle implémentation ou standard industriel.

Pour les bibliothèques, ca n'est pas son problème.



Je ne parle pas des biblothèques, mais de la bibliothèque C
spécifiée par la norme C. Faudrait apprendre à lire et à
utiliser ton cerveau!

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Avatar
Vincent Lefevre
Dans l'article <4bb85925$0$30018$,
Samuel DEVULDER écrit:

Vincent Lefevre a écrit :

> "Exposant binaire" signifie que cela donne 2^e. Je ne parle pas de
> l'écriture de l'exposant, mais de sa sémantique.

Ah ok. Il faut préciser car sur les docs (rares) décrivant %p, toutes
parlent d'exposant décimal et pas binaire.



Un conseil: évite ces docs et réfère-toi à la norme C ISO.

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Avatar
Samuel DEVULDER
Vincent Lefevre a écrit :
Dans l'article <4bb85925$0$30018$,
Samuel DEVULDER écrit:

Vincent Lefevre a écrit :



"Exposant binaire" signifie que cela donne 2^e. Je ne parle pas de
l'écriture de l'exposant, mais de sa sémantique.





Ah ok. Il faut préciser car sur les docs (rares) décrivant %p, toutes
parlent d'exposant décimal et pas binaire.



Un conseil: évite ces docs et réfère-toi à la norme C ISO.



Pourquoi? Parce que ca ne va pas dans ton sens? Non merci. Du reste
parler d'exposant décimal pour dire qu'on l'affiche en base dix est ce
qu'on appelle parler du français ou un anglais correct. Ce Je ne suis
pas tenté de mettre au feu ces docs sur ce seul fait. Par contre une doc
qui parlerait d'affichage binaire pour dire qu'on affiche en base dix
mériterait lui d'être sérieusement relu et ré-écrit. J'espère que la doc
ISO n'est pas comme ça.. mais que certains la lisent de travers peut être.

Est-ce que du serais du genre à consulter l'ensemble du texte législatif
sur le code de la route quand tu veux savoir si tu avait le droit de te
parquer en ville avec une roue légèrement dégonflée et un feu cassé du
coté opposé? La plupart des gens *NORMAUX* se passent très bien des
détails et vivent dans la pratique courante avec ce qu'ils ont retenu du
code Rousseau(c) qui leur a servi à passer le permis. Les gens normaux
utilisent le bon sens et les docs simplifiées pour se démerder dans la
vie. Les fondamentaliste (religieux ou autre) se réfèrent aux texte
sacré à tout propos et lapide l'impie qui refuse de rentrer dans leur
jeu. Les uns font avancer le monde, les autres le régresser.

Du reste tes conseils seraient plus utiles si tu passait l'URL de la
norme C-ISO au moins. Mais bon cela n'est pas bien important, je crois
que personne ne suit plus ce fil de discussion.

sam (il n'y a plus d'abonné au bout du fil).
Avatar
Samuel DEVULDER
Vincent Lefevre a écrit :

Tu n'as rien compris au C.



Ah? Ben ca alors, c'est rigolo, j'aurais dis que toi tu n'a rien compris
à l'usage courant du C :) Le C n'est pas une religion et celui qui
connait la bible^wnorme par coeur n'est pas meilleur pratiquant que
celui qui code tous les jours sur des matériels des plus divers dans des
environnement +- fidèle à la sacro sainte bible (qui sert à aider ceux
qui sont paumés par un truc qui les dépasse de toute façon).

Utiliser les types de base permet
d'être portable, contrairement à des types définis par telle
ou telle implémentation ou standard industriel.



**STOP**

Merci monsieur le prêcheur.. Reste dans ton église. Continue à parler
dans le vide.. pendant ce temps la le monde avance.

sam (les chiens aboient, la caravane passe).
Avatar
espie
In article <4bb9c85f$0$14936$,
Samuel DEVULDER wrote:
Vincent Lefevre a écrit :
Dans l'article <4bb85925$0$30018$,
Samuel DEVULDER écrit:

Vincent Lefevre a écrit :



"Exposant binaire" signifie que cela donne 2^e. Je ne parle pas de
l'écriture de l'exposant, mais de sa sémantique.





Ah ok. Il faut préciser car sur les docs (rares) décrivant %p, toutes
parlent d'exposant décimal et pas binaire.



Un conseil: évite ces docs et réfère-toi à la norme C ISO.



Pourquoi? Parce que ca ne va pas dans ton sens? Non merci. Du reste
parler d'exposant décimal pour dire qu'on l'affiche en base dix est ce
qu'on appelle parler du français ou un anglais correct. Ce Je ne suis
pas tenté de mettre au feu ces docs sur ce seul fait. Par contre une doc
qui parlerait d'affichage binaire pour dire qu'on affiche en base dix
mériterait lui d'être sérieusement relu et ré-écrit. J'espère que la doc
ISO n'est pas comme ça.. mais que certains la lisent de travers peut être.



Sam, arrete de raconter n'importe quoi. Vincent a raison. Si tu fais du C
en dilettante, ca te regarde, mais des que tu fais des trucs un peu complexes,
il est important de distinguer la representation interne (mantisse + exposant
binaire) de l'affichage (base 10, 16 ou autre) si on veut y comprendre quelque
chose.

Est-ce que du serais du genre à consulter l'ensemble du texte législatif
sur le code de la route quand tu veux savoir si tu avait le droit de te
parquer en ville avec une roue légèrement dégonflée et un feu cassé du
coté opposé? La plupart des gens *NORMAUX* se passent très bien des
détails et vivent dans la pratique courante avec ce qu'ils ont retenu du
code Rousseau(c) qui leur a servi à passer le permis. Les gens normaux
utilisent le bon sens et les docs simplifiées pour se démerder dans la
vie. Les fondamentaliste (religieux ou autre) se réfèrent aux texte
sacré à tout propos et lapide l'impie qui refuse de rentrer dans leur
jeu. Les uns font avancer le monde, les autres le régresser.



Blablabla... la plupart des gens normaux ne font pas du C. Dans ceux qui
en font, il y a plusieurs categories, dont ceux qui veulent ecrire du code
raisonnablement portable, qui ont defini le perimetre des machines sur
lesquelles c'est sense tourner. C'est le cas de Vincent, pour ce que je
connais de ses realisations. C'est aussi mon cas (plusieurs architectures).
D'autres, comme Wikka, ont egalement l'habitude de lire ET suivre des
specifications formelles, dans un contexte professionnel.

Au final, quand tu tombes sur un probleme, tu es regulierement oblige de
lire les specs officielles, pour savoir si:
- tu as ecrit de la merde, genre totalement non specifie ou autre;
- ton compilo/bibliotheque/systeme a un gros bug, qu'il va falloir
reporter/corriger (et trouver un work-around en attendant).
- tu as ecrit quelque chose qui marche dans le contexte qui t'interesse,
qui peut etre du C ISO99 + norme IEEE754, ou du POSIX 2008 sans norme IEEE754,
ou encore toalement autre chose.

Je ne crois pas que ca amuse qui que ce soit de jouer a ca, mais a partir
du moment ou tu fais du code qui est cense compiler ET fonctionner ailleurs
que sur ta machine/OS de depart, *tu n'as pas le choix*! Enfin si, tu l'as.
Tu peux soit te lire les normes et ecrire du code de qualite, ou attendre
qu'un utilisateur quelconque te dise que ton truc ne marche pas chez lui,
et perdre des heures a experimenter des trucs sans vraiment comprendre...

apres, c'est a toi de voir. Preferes-tu precher l'obscurantisme, ou profiter
de la bonne parole des gens qui savent un peu comment marchent les choses ?
Perso, je suis tres content que Vincent traine par ici, et je n'ai absolument
aucun doute quant a ses competences concernant les calculs en flottant, qui
sont largement plus importantes que la majorite des gens ici presents (et
je me compte dans les gens qui en utilisent largement moins que lui).

Du reste tes conseils seraient plus utiles si tu passait l'URL de la
norme C-ISO au moins. Mais bon cela n'est pas bien important, je crois
que personne ne suit plus ce fil de discussion.



Tu te trompes. Je suis encore la.

Pour la norme C, tu ne peux pas l'obtenir gratuitement de facon legale.
Tu peux trouver un brouillon quasi-final:
http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf
ainsi que le rationale:
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf

"la vraie" peut s'acheter aupres du comite ANSI, de memoire pour $18.

Il y a aussi une version papier editee par Wiley pour environ 50 EUR.
ISBN 0 470 84573 2
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

Vincent Lefevre a écrit :

Moi j'en parle: ton code avec long int n'est pas portable, et



Rahala... D'où sors tu que cet exemple voulait être portable?



Quel est l'intérêt à écrire du code non portable quand du code portable
est tout aussi aisé à écrire?

Du même chapeau que la machine 64?



Ça ne fait jamais que plus de 10 ans que j'ai une machine 64 bits sur
mon bureau au boulot. C'est plus récent à la maison.

Comme tous les pinailleurs[*] tu
noies le discours dans des trucs parfaitement inutiles.



Ce dont tu n'as pas l'utilité maintenant n'est pas nécessairement
inutile.

Il y a une chose dont tu ne te rends apparemment pas compte: les
pinailleurs sont simplement conscient de ce dont ils dépendent et
n'augmentent pas leurs dépendances inutilement.

Dans le cas présent, on veut voir ...



Les fils de discussion dévient. C'est ce qui en fait l'intérà ªt pour
certains, beaucoup que plus en tout cas que les questions originales.
On apprend quelque chose qu'on ne savait pas. On apprend que la
réalité ne correspond pas à ce qu'on croyait savoir.

Si ça ne te plait pas, il y des forums web dont le format, les
traditions, les modérateurs sont beaucoup moins favorables à ce g enre
de digression qu'Usenet (StackOverflow est un des plus extrêmes de ce
point de vue). Et qui sont beaucoup moins intéressants de ce fait à  
mon goût.

--
Jean-Marc
Avatar
Samuel DEVULDER
Marc Espie a écrit :

Sam, arrete de raconter n'importe quoi. Vincent a raison.



Il a raison? C'est pas moi qui dit que jetter quoi que ce soit. Les docs
dispo parlent d'exposant décimal dans le format du printf du %p.. pas
binaire. Et comme ca colle pas avec ce qu'il dit il jette sans
explication. Il ne faut pas abuser là quand même.

On est parti d'un pb simple: pourquoi (1.7f + 0.1) != (1.7 + 0.1) alors
que tous les deux s'affichent en %e de la même façon. On a répondu sur
les différentes façon de sortir le flottant mémoire à l'écran. La dessus
il débarque en critiquant l'utilisation de l'union, nous sort le %a sans
description avec un air supérieur, voir condescendant ("beurk"!). On
passe outre la condescendance pour comprendre ce format "%a". J'écris
que d'après les docs trouvées (rares) ce qui suit le "p" est décimal et
il nous sort "non! binaire".. ce qui est manifestement faux: on parle
ici d'affichage et pas de représentation mémoire.

Maintenant on peut dire qu'il a raison, mais je ne crois pas, sur ce
point là du moins. Après le reste ISO, etc guerre de clocher... moi je
m'en méfie: Vincent et Jean-Marc n'étaient même pas d'accord sur
l'utilisation légitime ou pas de l'union. Perso je suis un pragmatique:
si il y a une logique dans le code, que le compilo ne grogne pas (toutes
options allumées), et que le résultat est ok, alors pas besoin de se
compliquer la vie, surtout pour un bout de code d'exemple .. hein, pas
un truc destiné à être la refondation complète du langage C, où au noyau
d'un theorem-proveur... Il faut savoir *proportion garder*.

Blablabla...



Tu as raison... je me laisse aller. Je devrais être laconique et laisser
couler...

la plupart des gens normaux ne font pas du C. Dans ceux qui
en font, il y a plusieurs categories, dont ceux qui veulent ecrire du code
raisonnablement portable, qui ont defini le perimetre des machines sur
lesquelles c'est sense tourner. C'est le cas de Vincent, pour ce que je
connais de ses realisations. C'est aussi mon cas (plusieurs architectures).
D'autres, comme Wikka, ont egalement l'habitude de lire ET suivre des
specifications formelles, dans un contexte professionnel.



Oui mais qu'il ne vienne pas nous la raconter et juger des normes sur
d'autres domaines que les leurs. Elles ont leur propres raisons tout
aussi légitimes que son avi perso.

Par exemple, il s'offusque que Misra-C, puisque c'est d'elle dont il
s'agit, interdise aux utilisateurs d'utiliser les types de bases.
Pourtant il a pu juger par lui même que ça n'était pas n'importe quoi et
qu'un bout de code pour deux architectures différentes peut passer de
correct à incorrect. Mais au lieu de reconnaitre qu'il a tord sur ce
point il est partie dans la dérive sur "pourtant les libs l'utilisent"..
blabla blabla... bref un truc hors sujet par rapport à la norme du
départ (qui spécifie quelle libs ISO sont exclues).

Autre exemple.. la norme interdit l'utilisation de "==" et "!=" entre
deux floats.. et il s'en offusque encore avec un "pourtant c'est utile".
Utile? peut être pour ce qu'il fait, mais pas dans le domaine considéré
de la norme. Typiquement dans ce domaine on effectue des calculs
(nombreux) de modèle physiques et dans laquelle pour éviter des
divisions par zéro parce que deux valeurs sont trop proche on utilisera
plutôt un développement limité de la formule.

Misra est plus stricte que ISO-C, on y trouve des constructions
autorisées en ISO qui ne le sont pas en Misra, c'est tout, c'est comme
ça. Pas besoin d'épiloguer.


Au final, quand tu tombes sur un probleme, tu es regulierement oblige de
lire les specs officielles, pour savoir si:
- tu as ecrit de la merde, genre totalement non specifie ou autre;
- ton compilo/bibliotheque/systeme a un gros bug, qu'il va falloir
reporter/corriger (et trouver un work-around en attendant).
- tu as ecrit quelque chose qui marche dans le contexte qui t'interesse,
qui peut etre du C ISO99 + norme IEEE754, ou du POSIX 2008 sans norme IEEE754,
ou encore toalement autre chose.



Oui je suis d'accord: la norme on la sort quand on a un truc grave qu'on
ne sais pas régler. Mais pas sur un exemple jouet, ni dans des contextes
où elle ne s'applique pas.

Tu te trompes. Je suis encore la.



Je salue ton courage, bien que je pense que ce thread ne t'apprends pas
grand chose, sauf peut être étudier comment deux grand c*ns peuvent se
batte indéfiniment sur des futilités bien éloignées du pb original.

Pour la norme C, tu ne peux pas l'obtenir gratuitement de facon legale.
Tu peux trouver un brouillon quasi-final:
http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf
ainsi que le rationale:
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf



Merci à toi. Dommage qu'il faille passer par quelqu'un d'autre pour
avoir des infos précises.

sam.
Avatar
Samuel DEVULDER
Jean-Marc Bourguet a écrit :
Samuel DEVULDER writes:

Vincent Lefevre a écrit :

Moi j'en parle: ton code avec long int n'est pas portable, et


Rahala... D'où sors tu que cet exemple voulait être portable?



Quel est l'intérêt à écrire du code non portable quand du code portable
est tout aussi aisé à écrire?



Si on veut. Mais je ne fais pas cet effort pour un exemple jouet. C'est
pas une refonte de COQ ce code. (http://www.lix.polytechnique.fr/coq/)

Du même chapeau que la machine 64?



Ça ne fait jamais que plus de 10 ans que j'ai une machine 64 bits sur
mon bureau au boulot. C'est plus récent à la maison.



Peut être, mais quel est le lien avec la machine de Vicent ou avec le pb
d'utiliser deux longs pour y stocker un double? Dans tous les cas,
sizof==4 ou 8, il y a assez de bits pour y mettre le résultat. En plus
sizeof(long) == 8 c'est pas exactement un pb de machine, mais un pb de
compilo. Je n'ai pas bien compris l'intérêt qu'a Vincent à sortir cette
machine 64bits dans la mesure ou c'est juste pas le problème.

Comme tous les pinailleurs[*] tu
noies le discours dans des trucs parfaitement inutiles.



Ce dont tu n'as pas l'utilité maintenant n'est pas nécessairement
inutile.



Peut-être, oui. Mais j'avoue avoir du mal à trouver l'intérêt dans des
"beurk", "le code est faux" sans détails ou en l'absence de détails, des
digressions sur le fait que l'exposant après le "p" est binaire et pas
décimal.

Il y a une chose dont tu ne te rends apparemment pas compte: les
pinailleurs sont simplement conscient de ce dont ils dépendent et
n'augmentent pas leurs dépendances inutilement.

Dans le cas présent, on veut voir ...



Les fils de discussion dévient. C'est ce qui en fait l'intérêt pour
certains, beaucoup que plus en tout cas que les questions originales.
On apprend quelque chose qu'on ne savait pas. On apprend que la
réalité ne correspond pas à ce qu'on croyait savoir.



C'est pas faux. Mais ça mériterait de la part de certains posteurs
d'être didactiques et expliquer le pourquoi du comment un "beurk" ou un
"c'est faux". Si possible l'explication accompagnant le "beurk" dans le
même message, et pas après 3 réponses intermédiaires après moultes
provocations inutiles.

J'ai rien contre le fait qu'on me dise: ton code a un défaut quand on a
une machine/compilo qui ceci/cela.. Mais qu'on ne me dise pas: c'est
faux, ou pire "d'après la norme, c'est faux!". Car, outre le fait que je
ne réduise pas le C à une norme (il ya bcp de variations dans le C), je
ne crois pas forcément tout ce qu'on dit que la norme raconte. Je
préfère de loin les trucs expliqués comme il faut. Les arguments
d'autorités sont parfaitement inutiles et au lieu de convaincre, ils ont
tendance à braquer. Seul l'expérience (réele) ou virtuelle (i.e.
racontée) peut convaincre efficacement.

sam.
Avatar
espie
In article <4bb9fabd$0$22486$,
Samuel DEVULDER wrote:
Jean-Marc Bourguet a écrit :
Samuel DEVULDER writes:

Vincent Lefevre a écrit :

Moi j'en parle: ton code avec long int n'est pas portable, et


Rahala... D'où sors tu que cet exemple voulait être portable?



Quel est l'intérêt à écrire du code non portable quand du code portable
est tout aussi aisé à écrire?



Si on veut. Mais je ne fais pas cet effort pour un exemple jouet. C'est
pas une refonte de COQ ce code. (http://www.lix.polytechnique.fr/coq/)



A cote de ca, ce newsgroup est quand meme un peu une vitrine. Si on laisse
passer des erreurs, meme dans des exemples jouets, les gens qui passent par la
risquent de prendre ces erreurs comme argent comptant. Il y a deja
suffisamment de mauvais exemples de code C dans la nature, c'est peut-etre pas
necessaire d'en rajouter...

(bon, a cote, usenet is dying, c'est pas les 3 dinosaures qui trainent encore
ici qui vont se faire avoir...)
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

Jean-Marc Bourguet a écrit :
Ça ne fait jamais que plus de 10 ans que j'ai une machine 64 bits s ur
mon bureau au boulot. C'est plus récent à la maison.



Peut être, mais quel est le lien avec la machine de Vicent ou avec le
pb d'utiliser deux longs pour y stocker un double? Dans tous les cas,
sizof==4 ou 8, il y a assez de bits pour y mettre le résultat. E n plus
sizeof(long) == 8 c'est pas exactement un pb de machine, mais un pb de
compilo. Je n'ai pas bien compris l'intérêt qu'a Vincent à sortir
cette machine 64bits dans la mesure ou c'est juste pas le problème.



Je n'ai aucune idée de ce que donne ton code sur une Sparc 64 bits,
peut-être ce à quoi tu attends, peut-être les 32 bits de poi ds faibles
des deux long que tu passes, le deuxième étant donc non initialis é.
Il faudrait que je pense à tester -- au boulot et après la rentr ée, il
y a peu de chances que j'y pense en pratique. (Pq: Il me semble me
souvenir, mais je n'en suis pas sûr, que l'ABI sur Sparc passe les
paramètres par registres même dans le cas des arguments variadiqu es;
naturellement, tester sur un des OS ne garanti rien au sujet des
autres).

Je préfère de loin les trucs expliqués comme il faut. Les arguments
d'autorités sont parfaitement inutiles et au lieu de convaincre, ils
ont tendance à braquer. Seul l'expérience (réele) ou virtu elle
(i.e. racontée) peut convaincre efficacement.



Mon expérience est que les optimiseurs profitent de plus en plus de
tout ce qui est indéfini pour essayer de grater des perfs et qu'il est
difficile alors de prévoir ou même d'expliquer un comportement ob servé
sans en connaître le fonctionnement détaillé. On peut argue r qu'ils
dénaturent la raison pour laquelle certains de ces comportements sont
indéfinis, mais ça change pas grand chose.

C'est pourquoi je suis content d'avoir appris dans ce fil qqch sur les
unions (il me reste d'ailleurs à vérifier si c'est transposable en
C++).

--
Jean-Marc