2014-01-18 18 views
6

Ich habe MinGW GCC 4.8.1 und den folgenden Code ein:Vergleich der Summe der Quadratwurzeln

#include <iostream> 
#include <cmath> 

double eval(int a, int b){ 
    return std::sqrt(a) + std::sqrt(b); 
} 

int main(){ 
    double first = eval(545, 331); 
    double second = eval(545, 331); 

    if(first < second) 
     std::cout << "first < second" << std::endl; 
    if(first == second) 
     std::cout << "first == second" << std::endl; 
    if(first > second) 
     std::cout << "first > second" << std::endl; 
} 

Wenn mit -O0 zusammengestellt, das Programm druckt das erwartete Ergebnis:

first == second 

Wenn jedoch kompiliert mit -O1, -O2 oder -O3, das Programm aus: (das Ergebnis auf ideone)

first < second 
first == second 

Warum? Wie man es repariert?

+0

Auf coliru [druckt] (http://coliru.stacked-crooked.com/a/0faa177acceb3caa) 'first == second' für alle vier Flags (mit clang). – Shoe

+0

Mit QtCreator 3.0.0 habe ich das gleiche falsche Ergebnis für MinGW 4.8, während MSVC 2012 32 Bit und 64 Bit im Freigabemodus funktionieren. Alle Debug-Konfigurationen funktionieren jedoch. Seltsam. – Korchkidu

+0

Auch das Drucken der ersten und zweiten scheint die Ergebnisse zu ändern, je nachdem, ob sie vor oder nach den Vergleichen gedruckt werden. – Korchkidu

Antwort

5

In x86-Architekturen ist die Genauigkeit von Gleitkommazahlen 80-Bit, aber double hat nur 64-Bit. Und mit der GCC-Optimierung kann die Auswertung eines Ausdrucks, der eine Gleitkommazahl ergibt und auf einer double gespeichert wird, zu unterschiedlichen Werten führen, da die Optimierung die Anpassung der Gleitkommazahl an eine geringere Genauigkeit verändert.

Um das gleiche Ergebnis mit verschiedenen GCC-Otimierungen zu erhalten, verwenden Sie die Option -ffloat-store.