OVH Cloud OVH Cloud

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

10 réponses

2 3 4 5 6
Avatar
Jean-Marc Bourguet
Marc Boyer writes:

La démarche est, je pense, un peu différente de celle d'un simple
commentaire comme mis dans un entête. J'imagine (mais je peux me tromper),
qu'avant de considérer qu'un code C devient un code C++, on se renseigne
sur les différences entre les deux langages, et on regarde un peu
son code voire s'il utilise les constructions incriminées. Non ?



Non: tu compiles, fais tourner les tests et examine les resultats. Une
partie des changements avait ete fait avec des scripts, mais je ne me
souviens pas qu'ils cherchaient des differences de semantique, uniquement
des choses valables d'un cote et pas de l'autre + ajouter des extern "C"
pour un interfacage plus aise au code qui reste en C, etc. Chercher les
differences de semantiques de maniere automatique semble difficile, et le
code etait trop gros et les differences trop peu probable pour que les
chercher a la main soit envisageable.

> En passant, certains sont en train de faire modifier le code de gcc pour
> qu'il soit compilable en C++ et en C; avec comme effet qu'ils ont ajoute la
> possibilite d'avoir un warning sur certaines differences quand on compile
> en C.

C'est à dire, un message du genre "Warning: this construction has
a different semantics in C and C++" ?



Ou "Warning, void* can't be implicitly converted to int* in C++". Oui.

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:

Donc, je suis bien en 387, pas un iota de SSE*. Avec ou sans
l'option -mfpmath87, même résultat, l'option -ffloat-store
est sans effet. Même code à l'arrivée. J'ai vérifié aussi le
code assembleur généré.



Au contraire, tu montres qu'elle a toujours un effet. Tu disais:

|Et, sauf erreur, j'obtiens toujours, sans '-ffloat-store' :
|
| Les flottants c'est tabou = 999.999939
| On en viendra tous à bout = 1000.000000
|
|et avec '-ffloat-store' :
|
| Les flottants c'est tabou = 1000.000000
| On en viendra tous à bout = 1000.000000

Bref, j'en reviens toujours à la conclusion que c'est un bug
du compulateur.



Le fait que -ffloat-store introduise des load/store sur une expression
(ici, u / v / v / v) n'a pas forcément à être considéré comme un bug.
Quoique... cela peut contredire FLT_EVAL_METHOD.

--
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
espie
In article ,
Marc Boyer wrote:
La démarche est, je pense, un peu différente de celle d'un simple
commentaire comme mis dans un entête. J'imagine (mais je peux me tromper),
qu'avant de considérer qu'un code C devient un code C++, on se renseigne
sur les différences entre les deux langages, et on regarde un peu
son code voire s'il utilise les constructions incriminées. Non ?



Qu'est-ce qui te fait dire, dans le cas qui nous preoccupait au debut,
que les gens qui ont compile ce driver avec un compilo C++ ne savent
pas exactement ce qu'ils font ?

En particulier, ca n'est pas vraiment complique de trouver toutes les
raisons qui font qu'un programme C valide sera un programme C++ valide
de semantique differente... (le plus gros souci etant effectivement
sizeof('a'), pas exactement la construction qui va poser le plus de
probleme en pratique...)
Avatar
espie
In article <gqqeqk$hiu$,
Antoine Leca wrote:
Dans la pratique, on a les différences de nommages (et il y a export"C"
qui est fait pour), le type de NULL et quelques variations du même
genre, l'histoire du type de 'a' qui d'après ce que j'ai compris, sert
surtout à détecter le langage du compilateur :^), et dans les trucs plus
gênants, les utilisations de malloc() et le destin des const globales.



Euh non, ca sert surtout a faire fonctionner
std::cout << 'a';
de maniere intuitive, parce qu'on ne s'attend pas a ce que ca affiche '65',
mais bien 'a'...
Avatar
Kojak
Le Mon, 30 Mar 2009 16:45:30 +0000 (UTC),
Vincent Lefevre a écrit :

Dans l'article ,
Kojak écrit:
> [...] Même code à l'arrivée. J'ai vérifié auss i le
> code assembleur généré.

Au contraire, tu montres qu'elle a toujours un effet. Tu disais:

|Et, sauf erreur, j'obtiens toujours, sans '-ffloat-store' :



Je crois qu'il y a comme un malentendu. Le "sauf erreur, j'obtiens
toujours" faisait référence aux tests effectués avec les ver sions
4 de GCC (je n'avais pas, à ce moment, de version 3). Donc, au
temps pour moi, j'aurais dû le préciser.

> Bref, j'en reviens toujours à la conclusion que c'est un bug
> du compulateur.



Oops ! "... du compilateur." bien sûr. :-)

Je confirme, avec la version de GCC utilisée (3.4.6) le rajout de
-ffloat-store n'a aucun effet sur le résultat de la compilation.
Un peu comme si l'option avait été prévue dans le parser, ma is pas
activée. Un problème spécifique à la version Debian ? O u est-ce
général à toutes les version de GCC 3 (4.6 et autres) ? Là  , je ne
saurais dire.

Le fait que -ffloat-store introduise des load/store sur une expression
(ici, u / v / v / v) n'a pas forcément à être considé ré comme un bug.
Quoique... cela peut contredire FLT_EVAL_METHOD.



Bref, aurais-tu un exemple simple où, compilé avec GCC 3 (disons
la version 3.4.6, par exemple) le résultat serait différent avec
et sans -ffloat-store ? Parce que, pour ma part, si je me limite
à ce bout de code :

#include <stdio.h>
int main (void)
{
float x = 10.0, y = 0.1;
return printf ("x / y = %fn", x / y);
}

que ce soit, par exemple, avec ces options
"-W -Wall -m32 -mno-sse -mfpmath87"
ou avec celles-ci
"-W -Wall -m32 -mno-sse -mfpmath87 -ffloat-store"
j'obtiens strictement le même résultat avec GCC-3.4.6, alors qu'a vec
les version 4.[1|2|3] tout se passe bien, j'ai bien les résultats
escomptés en fonction de l'option positionnée ou pas (i.e. les
load/store intermédiaires dans le code d'assemblage).

Maintenant, il est possible aussi que je sois passé à coté d 'un
détail important...

Cordialement,

--
Jacques.
Avatar
Marc Boyer
On 2009-03-30, Marc Espie wrote:
In article ,
Marc Boyer wrote:
La démarche est, je pense, un peu différente de celle d'un simple
commentaire comme mis dans un entête. J'imagine (mais je peux me tromper),
qu'avant de considérer qu'un code C devient un code C++, on se renseigne
sur les différences entre les deux langages, et on regarde un peu
son code voire s'il utilise les constructions incriminées. Non ?



Qu'est-ce qui te fait dire, dans le cas qui nous preoccupait au debut,
que les gens qui ont compile ce driver avec un compilo C++ ne savent
pas exactement ce qu'ils font ?



C'est vrai, je ne suis pas dans leur tête, je me basais uniquement
le commentaire cité par Pierre.

En particulier, ca n'est pas vraiment complique de trouver toutes les
raisons qui font qu'un programme C valide sera un programme C++ valide
de semantique differente... (le plus gros souci etant effectivement
sizeof('a'), pas exactement la construction qui va poser le plus de
probleme en pratique...)



A mon sens, le plus pénible, ce serait
const int i=0; // extern en C / static en C++
Après, la différence de type de 'a' entre C et C++, c'est
visible, mais en effet, je pense qu'en pratique, ce ne doit
pas être le pire.

Marc Boyer
--
Au XXIème siècle, notre projet de société s'est réduit
à un projet économique...
Avatar
Vincent Lefevre
Dans l'article ,
Kojak écrit:

Je confirme, avec la version de GCC utilisée (3.4.6) le rajout de
-ffloat-store n'a aucun effet sur le résultat de la compilation.
Un peu comme si l'option avait été prévue dans le parser, mais pas
activée. Un problème spécifique à la version Debian ? Ou est-ce
général à toutes les version de GCC 3 (4.6 et autres) ? Là, je ne
saurais dire.



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).

Bref, aurais-tu un exemple simple où, compilé avec GCC 3 (disons
la version 3.4.6, par exemple) le résultat serait différent avec
et sans -ffloat-store ?



Compile ton code d'origine avec les optimisations...

Sans -ffloat-store, mais avec -O:

Les flottants c'est tabou = 1000.000000
On en viendra tous à bout = 1000.000000

En ajoutant -ffloat-store:

Les flottants c'est tabou = 999.999939
On en viendra tous à bout = 1000.000000

--
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
Jean-Marc Bourguet
Marc Boyer writes:

A mon sens, le plus pénible, ce serait
const int i=0; // extern en C / static en C++



Ce n'est pas une difference silentieuse (ca va foirer a l'edition de
liens). Le fait que void* doit se caster doit avoir plus d'occurences en
pratique.

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
[J'avais tapé la réponse rapidement avant d'aller manger.
Je supersedes, car la seconde partie était incorrecte.]

Dans l'article ,
Kojak écrit:

Je confirme, avec la version de GCC utilisée (3.4.6) le rajout de
-ffloat-store n'a aucun effet sur le résultat de la compilation.
Un peu comme si l'option avait été prévue dans le parser, mais pas
activée. Un problème spécifique à la version Debian ? Ou est-ce
général à toutes les version de GCC 3 (4.6 et autres) ? Là, je ne
saurais dire.



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).

Bref, aurais-tu un exemple simple où, compilé avec GCC 3 (disons
la version 3.4.6, par exemple) le résultat serait différent avec
et sans -ffloat-store ?



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.

Avec GCC 4.x:

ble:~> gcc -W -Wall -o peekaboo_store peekaboo.c -O2
ble:~> ./peekaboo_store
Les flottants c'est tabou = 999.999955
On en viendra tous à bout = 999.999955
ble:~> gcc -W -Wall -o peekaboo_store peekaboo.c -O2 -ffloat-store
ble:~> ./peekaboo_store
Les flottants c'est tabou = 1000.000000
On en viendra tous à bout = 1000.000000

Là on voit bien que le second résultat est *aussi* affecté par
-ffloat-store.

Quasiment de même (toujours le second résultat affecté), avec GCC 3.x:

ble:~> gcc-3.4 -W -Wall -o peekaboo_store peekaboo.c -O2
ble:~> ./peekaboo_store
Les flottants c'est tabou = 999.999955
On en viendra tous à bout = 999.999955
ble:~> gcc-3.4 -W -Wall -o peekaboo_store peekaboo.c -O2 -ffloat-store
ble:~> ./peekaboo_store
Les flottants c'est tabou = 999.999939
On en viendra tous à bout = 1000.000000

--
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
Vincent Lefevre
Dans l'article <20090331101358$,
Vincent Lefevre <vincent+ écrit:

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.



Note: au passage, le volatile a aussi pour effet que le 0.1 (non
représentable exactement en binaire) est converti en float, que
-ffloat-store soit utilisé ou non. Mais bon, l'important c'est
qu'on voit l'influence du -ffloat-store sur la séquence:

x = u / v;
y = x / v;
z = y / v;

avec GCC 3.x (3.4.6 dans mon cas). Ça se voit d'ailleurs en compilant
avec -S:

-O seul:

[...]
flds -4(%ebp)
flds -8(%ebp)
fdivrp %st, %st(1)
flds -8(%ebp)
fdivrp %st, %st(1)
flds -8(%ebp)
fdivrp %st, %st(1)
fstpl 4(%esp)
movl $.LC3, (%esp)
call printf
[...]

Les flds -8(%ebp) sont dus au fait que v est une variable volatile.
Mais on voit surtout qu'il n'y a pas de "store".

-O avec -ffloat-store:

[...]
flds -20(%ebp)
flds -24(%ebp)
fdivrp %st, %st(1)
fstps -8(%ebp)
flds -24(%ebp)
fdivrs -8(%ebp)
fstps -12(%ebp)
flds -24(%ebp)
fdivrs -12(%ebp)
fstps -16(%ebp)
flds -16(%ebp)
fstpl 4(%esp)
movl $.LC3, (%esp)
call printf
[...]

où les fstps/flds ont pour effet d'arrondir les résultats:
précision étendue -> simple précision.

--
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)
2 3 4 5 6