Le code ci-dessous fonctionne sur Visual Studio 2008 avec et sans optimisation. Mais il ne fonctionne que sur g++ sans optimisation (O0).
#include <cstdlib>
#include <iostream>
#include <cmath>
double round(double v, double digit)
{
double pow = std::pow(10.0, digit);
double t = v * pow;
//std::cout << "t:" << t << std::endl;
double r = std::floor(t + 0.5);
//std::cout << "r:" << r << std::endl;
return r / pow;
}
int main(int argc, char *argv[])
{
std::cout << round(4.45, 1) << std::endl;
std::cout << round(4.55, 1) << std::endl;
}
Le résultat devrait être:
4.5
4.6
Mais g++ avec optimisation (O1
- O3
) donnera comme résultat:
4.5
4.5
Si j'ajoute le mot clé volatile
avant t, cela fonctionne, y aurait-il un bug lié à l'optimisation?
Testé sur g++ 4.1.2 et 4.4.4.
Voici le résultat sur ideone: http://ideone.com/Rz937
Et l'option que j'ai testée sur g++ est simple:
g++ -O2 round.cpp
Le résultat le plus intéressant, même si j'active l'option /fp:fast
sur Visual Studio 2008, le résultat reste correct.
Question supplémentaire:
Je me demandais, devrais-je toujours activer l'option -ffloat-store
?
Parce que la version de g++ que j'ai testée est fournie avec CentOS/Red Hat Linux 5 et CentOS/Redhat 6.
J'ai compilé beaucoup de mes programmes sur ces plateformes, et je crains que cela ne provoque des bugs inattendus dans mes programmes. Il semble un peu difficile d'enquêter sur tout mon code C++ et les bibliothèques utilisées pour savoir s'ils ont de tels problèmes. Des suggestions?
Est-ce que quelqu'un s'intéresse au fait que même avec /fp:fast
activé, Visual Studio 2008 fonctionne toujours? Il semble que Visual Studio 2008 soit plus fiable sur ce problème que g++?
52 votes
Aux nouveaux utilisateurs de SO : VOICI comment poser une question. +1
1 votes
FWIW, je reçois la bonne sortie avec g++ 4.5.0 en utilisant MinGW.
0 votes
Je reçois 4.5 4.6 pour tous les cas. Quelle est votre version de g++? J'ai g++ (Debian 4.3.2-1.1) 4.3.2
0 votes
@Ours : Je ne peux pas reproduire cela avec GCC 4.5.3 ou 4.6.1, sur x86 ou x86_64. (Mais je n'ai aucune idée si c'est un bogue ou juste l'une des nombreuses vilénies concernant les nombres à virgule flottante.)
0 votes
Cela fonctionne comme prévu avec GCC 4.4.3 et 4.6.1 sur x86 avec ou sans
-std=c++0x
et avec n'importe lequel de-O0
,-O1
,-O2
et-O3
.0 votes
Je suis incapable de reproduire cela avec
g++ 4.4.3
sur Ubuntu 10.04 64 bits. Cela affiche4.5 4.6
avec et sans-O1
..-O3
.0 votes
FYI : gcc 4.6.1 (20110409) produit des résultats corrects sous Linux.
0 votes
G++ 4.6.1, les résultats sont corrects avec et sans optimisations.
0 votes
Sur g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2, j'obtiens la sortie correcte (
g++ -O3 x.cpp
, même chose pour-O[012]
)1 votes
Je me demande si cela a quelque chose à voir avec cela: gcc.gnu.org/gcc-4.5/changes.html "GCC a été intégré à la bibliothèque MPC. Cela permet à GCC d'évaluer plus précisément l'arithmétique complexe au moment de la compilation."
2 votes
Ideone utilise la version 4.3.4 ideone.com/b8VXg
5 votes
Tu devrais garder à l'esprit que ta routine n'est probablement pas fiable avec tous types de sortie. Contrairement à l'arrondi d'un double à un entier, cela est vulnérable au fait que tous les nombres réels ne peuvent pas être représentés, tu devrais donc t'attendre à obtenir plus de bugs comme celui-ci.
2 votes
Aux personnes qui ne peuvent pas reproduire le bug : ne décommentez pas les instructions de débogage commentées, elles affectent le résultat.
0 votes
N'a pas pu être reproduit sur gcc-4.5.1.
1 votes
De manière amusante, j'ai rencontré un problème similaire en 2006. À l'époque, j'ai été redirigé vers le rapport de bogue suivant : http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323.
0 votes
Je pourrais le reproduire sous x86_64 Linux avec les bons drapeaux, voir réponse ci-dessous.