2010-12-11 24 views
2

Werden Fließkommaberechnungen während der Kompilierungszeit oder während der Laufzeit ausgeführt, die konstante Ganzzahlen zum Kompilieren verwenden? Zum Beispiel, wenn die Teilungsoperation berechnet in:Fließkomma-Arithmetik zur Kompilierzeit

template <int A, int B> 
inline float fraction() 
{ 
    return static_cast<float>(A)/B; 
} 
+3

AFAIK der Standard definiert dies nicht und es hängt von den Compiler und Optimierungsflags ab. – khachik

+1

BTW, vergessen Sie nicht, dass Sie die Assembler-Ausgabe Ihres Compilers überprüfen können. Sie fragen nach Compiler-spezifischen, nicht sprachspezifischen Dingen. Ich wette, dass ein guter Compiler (vor allem mit Optimierungen) in der Kompilierzeit alles was er kann berechnen kann. – Kos

Antwort

1

Ich glaube, es ist die Implementierung definiert, aber die meisten Compiler werden konstante Ausdrücke zum Zeitpunkt der Kompilierung auswerten. Doch selbst wenn Ihr nicht die folgende Änderung:

template <int A, int B> 
inline float fraction() 
{ 
    static const float f = static_cast<float>(A)/B; 
    return f ; 
} 

wird zumindest dafür sorgen, dass der Ausdruck nur einmal ausgewertet wird, wenn es zur Laufzeit ausgewertet wird.

1

Ihre beste Wette auf dem generierten Code suchen ist - es gibt keine Garantie dafür, dass Floating-Point-Operationen werden bei der Kompilierung durchgeführt werden, aber bei höheren Optimierungsstufen sie könnten möglicherweise sein, besonders für etwas einfaches wie dieses.

(Einige Compiler könnten dies, weil vermeiden tun für einige Architekturen des Floating-Point-Verhalten zur Laufzeit konfiguriert werden. Die Ergebnisse für den Betrieb während der Kompilierung durchgeführt könnten dann möglicherweise von jenen unterscheiden, von der gleichen Operation zur Laufzeit durchgeführt.)

2

Für etwas so einfach, wird der Compiler wahrscheinlich es zur Kompilierzeit tun. Tatsächlich wird der Compiler wahrscheinlich zur Kompilierungszeit sogar ohne Templates tun, solange alle Werte zur Kompilierungszeit bekannt sind: d.h. wenn wir inline float fraction(int A, int B) haben, wird es wahrscheinlich die Division zur Kompilierungszeit machen, wenn wir fraction(1,2) aufrufen.

Wenn Sie Kraft wollen der Compiler Zeug zur Compile-Zeit zu tun, werden Sie einige Metaprogrammierung Tricks anwenden müssen, und ich bin nicht sicher, ob Sie es überhaupt mit Gleitkomma-Arithmetik zu arbeiten . Aber hier ist ein einfaches Beispiel für die Technik:

// Something similarly simple that doesn't use floating-point ;) 
template <int A, int B> 
struct Product { 
    enum { value = A * B }; 
}; 

// Later: 
... Product<3, 4>::value ... 
1

Sie für gcc warten sollen, 4.6 mit C++ 0x constexpr Keyword-Implementierung.

+1

Und während wir warten, und jeder andere Compiler einfach ignoriert C++ 0x, und * wenn * es jemals ratifiziert wird, wie sollen wir Arbeit erledigen? ;) – Clifford

1

Weder die C oder C++ Standards verlangen, dass konstante Ausdrücke jeder Streifen bei der Kompilierung ausgewertet werden, aber sie tun erlauben es. Die meisten Compiler, die in den letzten 20 Jahren veröffentlicht wurden, werden arithmetische Ausdrücke auswerten. Wenn Sie also keinen Funktionsaufruf oder Inline-Code benötigen, sollten Sie den Code so einfach wie möglich halten.

Wenn der Gültigkeitsbereich dieser Ausdrücke auf eine einzige Datei beschränkt ist, können Sie den Vorteil des Präprozessors und #define FRACTION(a,b) (float(a)/float(b)) aus praktischen Gründen immer nutzen. Ich empfehle nicht, dies in einer Kopfzeile zu tun, es sei denn, Sie haben ein gutes Schema, um zu verhindern, dass eine Datei, die #include ist, verschmutzt wird.

Verwandte Themen