Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Division et arrondi

54 réponses
Avatar
lhommedumatch
J'ai ce programme:
#include <iostream>
#include <math.h>

int main()
{
float x=3D10.0;
float y=3D1.0;
float scale=3D0.1;
int res;

res =3D int (x/scale);
std::cout << res << std::endl;
return 0;
}

Si je le compile avec:
version gcc 4.1.2 20071124 (Red Hat 4.1.2-42)
sur une machine 32bits j'obtiens 99
sur une machine 64bits j'obtiens 100

Quelqu'un pourrait m'=E9clairer.
Merci

4 réponses

2 3 4 5 6
Avatar
Kojak
Le Tue, 31 Mar 2009 10:21:37 +0000 (UTC),
Vincent Lefevre a écrit :

Non, -ffloat-store a bien un effet avec GCC 3.x, mais contrairement
à GCC 4.x, *uniquement* au niveau des affectations (même pas po ur
les casts). Lorsqu'on compile sans optimisation, ce n'est pas
visible, car chaque affectation a pour effet de copier le résultat
en mémoire, mais avec les optimisations, les résultats sont gar dés
par défaut dans les registres (ce qui est au passage un bug si le
type correspondant au registre est "plus gros" que le type de la
variable - bug 323 de GCC).



Bizarre autant qu'étrange ces comportements de GCC. Curieux aussi
cette nécessité d'optimiser pour valider l'option -ffloat-store,
sans compter les incohérences entre les différentes versions.

Il faut activer les optimisations, mais modifier ton code d'origine
pour que GCC évite de prendre en compte les constantes et de faire
les calculs à la compilation:

float f, x, y, z;
volatile float u = 1.0, v = 0.1;

Attention, le volatile ne doit se trouver que sur u et v, car
on veut toujours les optimisations sur les expressions.

[...]



Effectivement, en utilisant l'optimisation... Mais bon, je trouve
tout ça pas très orthodoxe, et surtout "embrouillogène".

Bref, les développeurs de GCC ont encore du pain sur la planche. :-)

Quoi qu'il en soit, merci pour l'info et les liens (via bug 323).

Cordialement,

--
Jacques.
Avatar
Jean-Marc Bourguet
Kojak writes:

Curieux aussi cette nécessité d'optimiser pour valider l'option
-ffloat-store,



-ffloat-store contraint l'optimisation. C'est donc pas etonnant qu'il
faille optimiser pour remarquer les differences induites dans
l'optimisation.

A+
--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Vincent Lefevre
Dans l'article ,
Kojak écrit:

Le Tue, 31 Mar 2009 10:21:37 +0000 (UTC),
Vincent Lefevre a écrit :



> Non, -ffloat-store a bien un effet avec GCC 3.x, mais contrairement
> à GCC 4.x, *uniquement* au niveau des affectations (même pas pour
> les casts). Lorsqu'on compile sans optimisation, ce n'est pas
> visible, car chaque affectation a pour effet de copier le résultat
> en mémoire, mais avec les optimisations, les résultats sont gardés
> par défaut dans les registres (ce qui est au passage un bug si le
> type correspondant au registre est "plus gros" que le type de la
> variable - bug 323 de GCC).



Bizarre autant qu'étrange ces comportements de GCC. Curieux aussi
cette nécessité d'optimiser pour valider l'option -ffloat-store,



Disons que l'option -ffloat-store telle qu'elle est documentée ne
devrait pas exister en C, puisque les store sont obligatoires lors
des affectations (sauf si le compilo peut prouver qu'ils ne changent
pas le résultat). Sans optimisation, les stores sont toujours générés
par le compilo, d'où la nécessité d'optimiser pour voir l'effet du
-ffloat-store (sans optimisation, le code généré reste correct).

sans compter les incohérences entre les différentes versions.



Oui. Les stores à l'intérieur d'une expression (générés par GCC 4.x)
ne sont pas nécessaires. D'une part, la norme C ne les impose pas,
et d'autre part, si le but est d'effectuer tous les calculs à la
précision (et plage d'exposants) des types utilisés, ces stores ne
règlent pas le problème du double arrondi. Ils peuvent être bénéfiques
à certains codes (sans aucune garantie et souvent sans possibilité
de le prouver), mais inversement, le double arrondi peut avoir pour
effet d'augmenter la borne d'erreur par rapport à ce que garantit la
norme C: l'arrondi au plus près permet d'obtenir une borne d'erreur
de 1/2 ulp (qui reste correcte lorsque les calculs intermédiaires sont
faits à une plus grande précision), mais en cas de double arrondi,
cette borne devient 1/2 ulp + 1/2 ulp' où ulp' est l'ulp correspondant
à la précision intermédiaire.

Note: si un double arrondi possible est prévu par la norme, e.g. lors
d'une affectation, celui qui fait l'analyse d'erreur doit de toute
façon le prendre en compte.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
Avatar
Antoine Leca
Le 01/04/2009 04:41Z, Kodak écrivit :
Bizarre autant qu'étrange ces comportements de GCC.



Je ne trouve pas.
Tout ceci vient d'une bonne raison : faire les choses « correctement » à
la fois coûte en perfs' et n'a pas d'effet notable pour 9x% des
utilisateurs de GCC (x étant une v.a. variant entre 0 et 9,9999).
À partir de là, les développeurs de GCC ne se sont pas encore fait une
religion (en fait ils s'en étaient faite une dans le bug 323, mais ils
sont revenus dessus), et ils louvoient, implémentant certaines choses
qui sont effectivement choquantes, et laissant de côté d'autres qui
semblent plus anodins... jusqu'au jour où cela revient leur sauter à la
figure.

Il faut bien voir que c'est un classique du respect d'une norme : tant
que cela ne coûte rien ou presque, il n'y a de problème pour personne à
partir du moment où le problème est détecté ; ainsi, le fait qu'un
résultat entier intermédiaire stocké dans un unsigned char ou transtypé
en unsigned short (éventuellement au travers d'un appel de fonction)
doivent être traduit par le compilateur comme une opération de masquage
si l'optimiseur a déterminé qu'il n'y a pas besoin de stockage
intermédiaire a pris quelques années vers 1990, mais maintenant c'est
bien acquis (notons au passage qu'un problème du même acabit a fait
exploser une fusée...)
Si l'opération est chère, il y a déjà nettement moins d'enthousiasme :
c'est ainsi qu'en C, les architectures en complément à 1 ou
signe+magnitude ne sont pas obligées de simuler le comportement du
complément à 2 (il y a d'autres langages où elles le sont), car le faire
les rendraient inopérantes. Idem pour la taille de ptrdiff_t:
normalement la mantisse de ce type devrait être un bit plus grande que
la taille des pointeurs, donc que la taille de size_t ; en pratique cela
obligerait beaucoup d'architectures à utiliser long long pour ptrdiff_t,
et là on voit bien que cela coulerait immédiatement l'intérêt du type,
qui est déjà sous-utilisé : aussi l'on s'accommode d'un ptrdiff_t
rabougri, et on fait semblant d'ignorer les problèmes qui vont survenir
maintenant que certaines applis 32 bits flirtent avec les 4Go, ou on
fait confiance à l'arithmétique en complément à 2 pour en réduire les
effets (ce qui est une attitude carrément dangereuse).

Pour en revenir à nos flottants, d'abord il faut voir que le cas à
problème est plutôt rare, il faut soit une machine avec précision
étendue (typiquement x87) mais où l'on veut avoir les mêmes résultats
qu'en double, soit un code qui utilise de la simple précision voire un
mélange entre les deux précisions : dans les deux cas, on a affaire à
des spécialistes de Q-v.
Ensuite, on est dans un monde assis entre plusieurs chaises, où en plus
des développeurs de GCC et des spécialistes numériques, on a les
responsables de la libc ou de l'architecture processeur, qui ne veulent
pas particulièrement entendre parler de modification drastique de
drapeaux de contrôle du NDP87, ou qui veulent promouvoir leur dernier
bébé (genre SSE35)...


Je finirais par une petite remarque : je pense que si à l'origine les
deux architectures t'avaient donné(e) le même résultat, tu n'aurais pas
trouvé cela aussi étrange ou bizarre, MÊME si le dit résultat avait été
99 : au plus tu aurais cherché un peu à comprendre pourquoi tu avais ce
résultat, et tu aurais eu l'explication très rapidement ; c'est
l'occurrence des deux résultats différents qui te préoccupe. Mais il
faut alors se poser une question : quelle est l'importance d'avoir deux
résultats possibles, si l'opération initiale est erronée ?


Antoine
2 3 4 5 6