2012-05-21 4 views
12

-freciprocal-math in GCC den folgenden CodeWarum ist -freccroal-math in GCC unsicher?

double a = b/c; 

zu

double tmp = 1/c; 
double a = b * tmp; 

In GCC Handbuch ändert, wird ihm gesagt, dass eine solche Optimierung unsicher ist und nicht auf IEEE-Standards klebt. Aber ich kann mir kein Beispiel vorstellen. Können Sie ein Beispiel geben?

+1

Betrachten Sie b = c = 3 –

+0

Ich habe nicht IEEE Regeln darüber, wie ein Compiler Fließkomma verwenden muss. Zum Beispiel ist X^2 oft stark auf X * X reduziert, wodurch typischerweise schnellere Programme erzeugt werden, jedoch mit einem anderen Fehler als die vom ursprünglichen Programmierer angegebene Berechnung. Also, @Kid, haben Sie sich den IEEE-Standard angeschaut, um zu sehen, welche Grenzen er Compilern mit solcher Arithmetik auferlegt? –

+0

@RaymondChen: Nach der IEEE-Rundung (nach oben? Nach unten? Sogar? Keine?) Wird vielleicht nicht Ihr b = c = 3-Beispiel das exakt gleiche Ergebnis in einem? –

Antwort

12

Dividieren durch 10 und Multiplizieren mit 0,10000000000000000555511151231257827021181583404541015625 sind nicht dasselbe.

+0

Wahr ist es nicht. Aber dann gibt dir der Fließkommawert keine präzise Antwort, wenn du durch zehn dividierst. Das Argument hier scheint also zu sein, wie viel Fehler Sie in Ihrer Fließkommaarithmetik akzeptieren wollen. Wenn Sie den Standard-IEEE-Float-Befehl ausführen, erhalten Sie einen gewissen Fehler bei der Berechnung (einschließlich eines vollständigen Genauigkeitsverlusts unter bestimmten Umständen). Wenn Sie reziproke Berechnungen durchführen, erhalten Sie keinen IEEE-definierten Gleitkommafehler. ob Sie mehr oder weniger bekommen, hängt von der tatsächlichen Berechnung ab, die Sie machen. –

+1

@IraBaxter, division gibt Ihnen ein genaues Ergebnis, wenn beide Operanden genau dargestellt werden, und zwar für Integer-Werte. –

+0

@MarkRansom: Wie bekomme ich ein präzises (du meinst genau?) Ergebnis für "1.0/3.0"? –

0

Vielleicht von einem anderen Compiler-Flag Ich denke, aber ...

Einige Prozessoren haben Anweisungen für die ungefähre reziproke Berechnung. RCPSS om der x86 (SIMD-Anweisung) kommt in den Sinn; Es hat einen relativen Fehler von 1,5 * 2^-12. Die Verwendung dieses Flags kann dem Compiler erlauben, einen annähernd reziproken Befehl auszuwählen, der in Abhängigkeit von Ihrer Anwendung möglicherweise nicht sicher ist.

Hoffe, das hilft.

+0

Mit GCC ist dies das Flag -mcip. – janneb

Verwandte Themen