Ich habe das folgende Bit Code, aber wenn ich es mit GCC 4.4 mit verschiedenen Optimierungsflags kompiliere, erhalte ich einige unerwartete Ergebnisse, wenn es ausgeführt wird.GCC-Problem mit rohen Doppeltyp-Vergleichen
#include <iostream>
int main()
{
const unsigned int cnt = 10;
double lst[cnt] = { 0.0 };
const double v[4] = { 131.313, 737.373, 979.797, 731.137 };
for(unsigned int i = 0; i < cnt; ++i) {
lst[i] = v[i % 4] * i;
}
for(unsigned int i = 0; i < cnt; ++i) {
double d = v[i % 4] * i;
if(lst[i] != d) {
std::cout << "error @ : " << i << std::endl;
return 1;
}
}
return 0;
}
, wenn sie mit kompiliert: "g ++ -pedantic -Wall Werror -O1 -o Test test.cpp" ich folgende Ausgabe: "Fehler @ 3"
, wenn sie mit kompiliert: "g ++ -pedantic -Wall Werror -O2 -o Test test.cpp" ich folgende Ausgabe: "Fehler @ 3"
, wenn sie mit kompiliert: "g ++ -pedantic -Wall Werror O3 -o Test test.cpp" Ich bekomme keine Fehler
, wenn sie mit kompiliert: „g ++ -pedantic -Wall - Werror -o Test test.cpp“ ich keine Fehler
ich glaube nicht, dass dies ein Problem zu Rundung oder epsilon Unterschied im Vergleich mit Bezug zu sein. Ich habe dies mit Intel v10 und MSVC 9.0 versucht und sie scheinen alle wie erwartet zu funktionieren. Ich glaube, das sollte nicht mehr als ein bitweiser Vergleich sein.
Wenn ich die if-Anweisung mit der folgenden ersetzen: if (static_cast<long long int>(lst[i]) != static_cast<long long int>(d))
, und fügen Sie „-Wno-lang-lang“ bekomme ich keine Fehler in einem der Optimierungsmodi bei der Ausführung.
Wenn ich std::cout << d << std::endl;
vor dem „Return 1“ hinzufügen, bekomme ich keine Fehler in einem der Optimierungsmodi bei der Ausführung.
Ist das ein Fehler in meinem Code, oder ist etwas nicht in Ordnung mit GCC und der Art, wie es den doppelten Typ behandelt?
Hinweis: Ich habe gerade dies mit GCC-Versionen 4.3 und 3.3 versucht, der Fehler wird nicht angezeigt.
Auflösung: Mike Dinsdale nahm den folgenden Fehlerbericht: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 Es scheint, das GCC-Team ist nicht ganz sicher über die Natur des Problems.
Wie im Fehlerbericht vorgeschlagen, besteht eine mögliche Lösung darin, die Option ffloat-store zu verwenden. Ich habe das versucht und es funktioniert, aber die Ergebnisse aus Sicht der Leistung sind nicht so toll, aber ymmv.
Vergleichen Sie 'doubles' am besten mit einem kleinen Delta-Wert, um Gleitkomma-Ungenauigkeiten zu berücksichtigen. Versuchen Sie, die Werte von "lst [i]" und "d" direkt vor dem Vergleich auszudrucken und lassen Sie uns wissen, wie unterschiedlich sie sind. – dirkgently
Dies ist kein Szenario, wo ich Werte aus verschiedenen Quellen erzeugt habe und ich möchte sehen, ob sie innerhalb einer Toleranz gleich sind, diese sind identische Werte (bitweise), sie sollten wahr vergleichen. Die Tatsache, dass der Compiler keine Binärdatei erzeugt, die eine konsistente Menge von Ausgaben liefert, ist beunruhigend. –
@Momoner: Wenn Sie das Programm so ändern, dass anstelle der FPU ein bitweiser Vergleich verwendet wird, ändern Sie die Baugruppe. Scheint grundlegend, aber das bedeutet, es wird nicht die Werte auf der FPU verwenden, die ausgeschaltet sein können, und tatsächlich laden und möglicherweise kürzen sie. Einfach gesagt, Ihr Test ist nicht schlüssig. – GManNickG