/fp
(Angeben des Gleitkommaverhaltens)
Gibt an, wie der Compiler Gleitkommaausdrücke, Optimierungen und Ausnahmen behandelt. Die /fp
Optionen geben an, ob der generierte Code Gleitkommaumgebungsänderungen im Rundungsmodus, Ausnahmemasken und Unternormalverhalten zulässt und ob Gleitkommastatusprüfungen aktuelle, genaue Ergebnisse zurückgeben. Er steuert, ob der Compiler Code generiert, der die Quellvorgangs- und Ausdrucksreihenfolge verwaltet, und entspricht dem Standard für die NaN-Verteilung. Oder wenn sie stattdessen effizienteren Code generiert, der Vorgänge neu anordnen oder kombinieren kann, und vereinfachende algebraische Transformationen, die vom IEEE-754-Standard nicht zulässig sind.
Syntax
/fp:contract
/fp:except
[-
]
/fp:fast
/fp:precise
/fp:strict
/fp:except
[-
]
/fp:fast
/fp:precise
/fp:strict
Argumente
/fp:contract
Mit /fp:contract
der Option kann der Compiler Gleitkommakontraktionen generieren, wenn Sie die /fp:precise
Optionen /fp:except
angeben. Eine Kontraktion ist eine Maschinenanweisung, die Gleitkommavorgänge wie Fused-Multiplikations-Add (FMA) kombiniert. FMA, definiert als basisbasierter Betrieb durch IEEE-754, rundet das Zwischenprodukt nicht vor dem Zusatz ab, sodass sich das Ergebnis von separaten Multiplikations- und Additionsvorgängen unterscheiden kann. Da sie als einzelne Anweisung implementiert wird, kann sie schneller als separate Anweisungen sein. Die Geschwindigkeit kostet bitweise genaue Ergebnisse und eine Unfähigkeit, den Zwischenwert zu untersuchen.
Standardmäßig aktiviert /fp:contract
die /fp:fast
Option . Die /fp:contract
Option ist nicht kompatibel mit /fp:strict
.
Die /fp:contract
Option ist neu in Visual Studio 2022.
/fp:precise
Standardmäßig verwendet /fp:precise
der Compiler verhalten.
Im Folgenden /fp:precise
behält der Compiler die Quellausdrucksortierungs- und Rundungseigenschaften von Gleitkommacode bei, wenn er Objektcode für den Zielcomputer generiert und optimiert. Der Compiler rundet während der Ausdrucksauswertung auf die Quellcodegenauigkeit zu vier bestimmten Punkten ab: bei Zuordnungen, Typecasts, wenn Gleitkommaargumente an einen Funktionsaufruf übergeben werden und wenn ein Funktionsaufruf einen Gleitkommawert zurückgibt. Zwischenberechnungen können bei der Maschinengenauigkeit durchgeführt werden. Typecasts können zum expliziten Runden von Zwischenberechnungen verwendet werden.
Der Compiler führt keine algebraischen Transformationen für Gleitkommaausdrücke aus, z. B. eine Erneute Zuordnung oder Verteilung, es sei denn, die Transformation kann garantieren, dass ein bitweises identisches Ergebnis entsteht. Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, werden gemäß IEEE-754-Spezifikationen verarbeitet. Beispielsweise wird ausgewertettrue
, x != x
ob x
naN ist. Gleitkommakontraktionen werden standardmäßig nicht generiert unter /fp:precise
. Dieses Verhalten ist neu in Visual Studio 2022. In früheren Compilerversionen können Kontraktionen standardmäßig unter /fp:precise
.
Der Compiler führt keine algebraischen Transformationen für Gleitkommaausdrücke aus, z. B. eine Erneute Zuordnung oder Verteilung, es sei denn, die Transformation kann garantieren, dass ein bitweises identisches Ergebnis entsteht. Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, werden gemäß IEEE-754-Spezifikationen verarbeitet. Beispielsweise wird ausgewertettrue
, x != x
ob x
naN ist. Gleitkommakontraktionen können unter /fp:precise
.
Der Compiler generiert Code, der in der Standard-Gleitkommaumgebung ausgeführt werden soll. Außerdem wird davon ausgegangen, dass zur Laufzeit nicht auf die Gleitkommaumgebung zugegriffen oder geändert wird. Das heißt, es wird davon ausgegangen, dass der Code: Lässt Gleitkomma-Ausnahmen maskiert, liest oder schreibt keine Gleitkommastatusregister und ändert keine Rundungsmodi.
Wenn Ihr Gleitkommacode nicht von der Reihenfolge von Vorgängen und Ausdrücken in Ihren Gleitkommaanweisungen abhängt (z. B. wenn Sie sich nicht um die Berechnung (b + c) * a
als oder 2 * a
as a + a
kümmern), sollten Sie die /fp:fast
Option in Betracht ziehena * b + a * c
, die schnelleren, effizienteren Code erzeugen kann. Wenn Ihr Code beide von der Reihenfolge von Vorgängen und Ausdrücken abhängt und auf die Gleitkommaumgebung zugreift oder ändert (z. B. um Roundingmodi zu ändern oder Gleitkommaausnahmen abzufangen), verwenden Sie /fp:strict
.
/fp:strict
/fp:strict
weist ein ähnliches Verhalten auf /fp:precise
, d. h., der Compiler behält die Quellsortierungs- und Rundungseigenschaften von Gleitkommacode bei, wenn er Objektcode für den Zielcomputer generiert und optimiert, und beobachtet den Standard beim Behandeln von Sonderwerten. Das Programm kann auch sicher auf die Gleitkommaumgebung zur Laufzeit zugreifen oder ändern.
Unter /fp:strict
diesem Code generiert der Compiler Code, mit dem das Programm Gleitkomma-Ausnahmen sicher entmasken, Gleitkommastatusregister lesen oder schreiben oder Roundingmodi ändern kann. Sie rundet auf die Quellcodegenauigkeit an vier bestimmten Punkten während der Ausdrucksauswertung ab: bei Zuordnungen, Typecasts, wenn Gleitkommaargumente an einen Funktionsaufruf übergeben werden und wenn ein Funktionsaufruf einen Gleitkommawert zurückgibt. Zwischenberechnungen können bei der Maschinengenauigkeit durchgeführt werden. Typecasts können zum expliziten Runden von Zwischenberechnungen verwendet werden. Der Compiler macht keine algebraischen Transformationen für Gleitkommaausdrücke, wie z. B. die Neuzuordnung oder Verteilung, es sei denn, sie kann garantieren, dass die Transformation ein bitweise identisches Ergebnis erzeugt. Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, werden gemäß IEEE-754-Spezifikationen verarbeitet. Beispielsweise wird ausgewertettrue
, x != x
ob x
naN ist. Gleitkommakontraktionen werden unter /fp:strict
quot; nicht generiert.
/fp:strict
ist rechenintensiver als /fp:precise
weil der Compiler zusätzliche Anweisungen einfügen muss, um Ausnahmen abzufangen und Programmen den Zugriff auf die Gleitkommaumgebung zur Laufzeit zu ermöglichen. Wenn Ihr Code diese Funktion nicht verwendet, aber Quellcode sortieren und runden muss oder auf speziellen Werten basiert, verwenden Sie /fp:precise
. Ziehen Sie andernfalls die Verwendung in /fp:fast
Betracht, die schnelleren und kleineren Code erzeugen kann.
/fp:fast
Mit /fp:fast
der Option kann der Compiler Gleitkommavorgänge neu anordnen, kombinieren oder vereinfachen, um Gleitkommacode für Geschwindigkeit und Platz zu optimieren. Der Compiler kann das Runden bei Zuordnungsanweisungen, Typecasts oder Funktionsaufrufen weglassen. Sie kann Vorgänge neu anordnen oder algebraische Transformationen vornehmen, z. B. durch Verwendung von assoziativen und verteilungsrechtlichen Gesetzen. Es kann Code neu anordnen, auch wenn solche Transformationen zu einem observablen unterschiedliche Rundungsverhalten führen. Aufgrund dieser verbesserten Optimierung kann sich das Ergebnis einiger Gleitkommaberechnungen von den von anderen /fp
Optionen erzeugten unterscheiden. Sonderwerte (NaN, +infinity, -infinity, -0,0) werden möglicherweise nicht gemäß dem IEEE-754-Standard weitergegeben oder verhalten. Gleitkommakontraktionen können unter /fp:fast
. Der Compiler ist nach wie vor an die zugrunde liegende Architektur /fp:fast
gebunden, und weitere Optimierungen können über die Verwendung der /arch
Option verfügbar sein.
Unter /fp:fast
diesem Code generiert der Compiler Code, der in der Standard-Gleitkommaumgebung ausgeführt werden soll, und geht davon aus, dass zur Laufzeit nicht auf die Gleitkommaumgebung zugegriffen oder geändert wird. Das heißt, es wird davon ausgegangen, dass der Code: Lässt Gleitkomma-Ausnahmen maskiert, liest oder schreibt keine Gleitkommastatusregister und ändert keine Rundungsmodi.
/fp:fast
ist für Programme vorgesehen, die keine strikte Quellcodesortierung und Rundung von Gleitkommaausdrücken erfordern und nicht auf die Standardregeln für die Behandlung spezieller Werte wie z NaN
. B. basieren. Wenn Ihr Gleitkommacode die Erhaltung der Quellcodesortierung und -rundung erfordert oder das Standardverhalten spezieller Werte verwendet, verwenden Sie /fp:precise
. Wenn Ihr Code auf die Gleitkommaumgebung zugreift oder ändert, um Rundungsmodi zu ändern, Gleitkomma-Ausnahmen aufzuheben oder den Gleitkommastatus zu überprüfen, verwenden Sie /fp:strict
.
/fp:except
Die /fp:except
Option generiert Code, um zu gewährleisten, dass alle ungemasketen Gleitkomma-Ausnahmen an dem genauen Punkt ausgelöst werden, an dem sie auftreten, und dass keine anderen Gleitkomma-Ausnahmen ausgelöst werden. Standardmäßig wird die /fp:strict
Option aktiviert /fp:except
und /fp:precise
nicht. Die /fp:except
Option ist nicht kompatibel mit /fp:fast
. Die Option kann mithilfe von /fp:except-
.
/fp:except
Allein werden keine Gleitkomma-Ausnahmen aktiviert. Es ist jedoch erforderlich, dass Programme Gleitkomma-Ausnahmen aktivieren. Weitere Informationen zum Aktivieren von Gleitkomma-Ausnahmen finden Sie unter _controlfp
.
Hinweise
Mehrere /fp
Optionen können in derselben Compiler-Befehlszeile angegeben werden. Es kann jeweils nur eine der /fp:strict
Optionen /fp:fast
/fp:precise
und Optionen wirksam sein. Wenn Sie mehr als eine dieser Optionen in der Befehlszeile angeben, hat die spätere Option Vorrang, und der Compiler generiert eine Warnung. Die /fp:strict
Optionen sind /fp:except
nicht kompatibel mit /clr
.
Die /Za
Option (ANSI-Kompatibilität) ist nicht kompatibel mit /fp
.
Verwenden von Compilerdirektiven zum Steuern des Gleitkommaverhaltens
Der Compiler stellt drei Pragmadirektiven bereit, um das in der Befehlszeile angegebene Gleitkommaverhalten außer Kraft zu setzen: float_control
, fenv_access
und fp_contract
. Sie können diese Direktiven verwenden, um das Gleitkommaverhalten auf Funktionsebene zu steuern, nicht innerhalb einer Funktion. Diese Direktiven entsprechen nicht direkt den /fp
Optionen. In dieser Tabelle wird gezeigt, wie sich die /fp
Optionen und Pragma-Direktiven einander zuordnen. Weitere Informationen finden Sie in der Dokumentation zu den einzelnen Optionen und Pragma-Direktiven.
Option | float_control(precise, *) |
float_control(except, *) |
fenv_access(*) |
fp_contract(*) |
---|---|---|---|---|
/fp:fast |
off |
off |
off |
on |
/fp:precise |
on |
off |
off |
off * |
/fp:strict |
on |
on |
on |
off |
* In Versionen von Visual Studio vor Visual Studio 2022 ist das /fp:precise
Verhalten standardmäßig auf fp_contract(on)
.
Option | float_control(precise, *) |
float_control(except, *) |
fenv_access(*) |
fp_contract(*) |
---|---|---|---|---|
/fp:fast |
off |
off |
off |
on |
/fp:precise |
on |
off |
off |
on * |
/fp:strict |
on |
on |
on |
off |
* In Versionen von Visual Studio ab Visual Studio 2022 wird standardmäßig das /fp:precise
Verhalten verwendet fp_contract(off)
.
Die Standard-Gleitkommaumgebung
Wenn ein Prozess initialisiert wird, wird die Standard-Gleitkommaumgebung festgelegt. Diese Umgebung maskiert alle Gleitkomma-Ausnahmen, legt den Rundungsmodus so fest, dass er auf die nächsten (FE_TONEAREST
), unternormalen (Denormal)-Werten gerundet wird, verwendet die Standardgenauigkeit von Significand (Mantissa) für float
, double
und long double
Werte, und wo unterstützt, legt das Unendlichkeitssteuerelement auf den Standardaffin-Modus fest.
Zugriff und Änderung der Gleitkommaumgebung
Die Microsoft Visual C++-Laufzeit bietet mehrere Funktionen, um auf die Gleitkommaumgebung zuzugreifen und sie zu ändern. Dazu gehören _controlfp
, _clearfp
und _statusfp
ihre Varianten. Um das richtige Programmverhalten sicherzustellen, wenn Ihr Code auf die Gleitkommaumgebung zugreift oder ändert, fenv_access
muss entweder durch die /fp:strict
Option oder die Verwendung des fenv_access
Pragmas aktiviert werden, damit diese Funktionen auswirkungen haben. Wenn fenv_access
diese Option nicht aktiviert ist, kann der Zugriff oder die Änderung der Gleitkommaumgebung zu unerwartetem Programmverhalten führen:
Code berücksichtigt möglicherweise nicht angeforderte Änderungen an der Gleitkommaumgebung,
Die Gleitkommastatusregister melden möglicherweise keine erwarteten oder aktuellen Ergebnisse,
Unerwartete Gleitkomma-Ausnahmen können auftreten oder erwartete Gleitkomma-Ausnahmen können nicht auftreten.
Wenn Ihr Code auf die Gleitkommaumgebung zugreift oder ändert, müssen Sie vorsichtig sein, wenn Sie Code kombinieren, der fenv_access
mit Code aktiviert ist, der nicht fenv_access
aktiviert ist. In Code, in dem fenv_access
nicht aktiviert ist, geht der Compiler davon aus, dass die Plattformstandard-Gleitkommaumgebung wirksam ist. Außerdem wird davon ausgegangen, dass auf den Gleitkommastatus nicht zugegriffen oder geändert wird. Es wird empfohlen, die lokale Gleitkommaumgebung in ihrem Standardzustand zu speichern und wiederherzustellen, bevor das Steuerelement auf eine Funktion übertragen wird, die nicht aktiviert ist fenv_access
. In diesem Beispiel wird veranschaulicht, wie das float_control
Pragma festgelegt und wiederhergestellt werden kann:
#pragma float_control(precise, on, push)
// Code that uses /fp:strict mode
#pragma float_control(pop)
Gleitkomma-Rundungsmodi
Sowohl unter als auch /fp:precise
/fp:fast
, generiert der Compiler Code, der in der Standard-Gleitkommaumgebung ausgeführt werden soll. Es wird davon ausgegangen, dass zur Laufzeit nicht auf die Umgebung zugegriffen oder geändert wird. Das heißt, der Compiler geht davon aus, dass der Code niemals Gleitkomma-Ausnahmen entpackt, Gleitkommastatusregister liest oder schreibt oder Roundingmodi ändert. Einige Programme müssen jedoch die Gleitkommaumgebung ändern. In diesem Beispiel werden beispielsweise Fehlergrenzen für eine Gleitkomma-Multiplikation durch Ändern von Gleitkomma-Rundungsmodi berechnet:
// fp_error_bounds.cpp
#include <iostream>
#include <limits>
using namespace std;
int main(void)
{
float a = std::<float>::max();
float b = -1.1;
float cLower = 0.0;
float cUpper = 0.0;
unsigned int control_word = 0;
int err = 0;
// compute lower error bound.
// set rounding mode to -infinity.
err = _controlfp_s(&control_word, _RC_DOWN, _MCW_RC);
if (err)
{
cout << "_controlfp_s(&control_word, _RC_DOWN, _MCW_RC) failed with error:" << err << endl;
}
cLower = a * b;
// compute upper error bound.
// set rounding mode to +infinity.
err = _controlfp_s(&control_word, _RC_UP, _MCW_RC);
if (err)
{
cout << "_controlfp_s(&control_word, _RC_UP, _MCW_RC) failed with error:" << err << endl;
}
cUpper = a * b;
// restore default rounding mode.
err = _controlfp_s(&control_word, _CW_DEFAULT, _MCW_RC);
if (err)
{
cout << "_controlfp_s(&control_word, _CW_DEFAULT, _MCW_RC) failed with error:" << err << endl;
}
// display error bounds.
cout << "cLower = " << cLower << endl;
cout << "cUpper = " << cUpper << endl;
return 0;
}
Da der Compiler die Standard-Gleitkommaumgebung unternimmt /fp:fast
und /fp:precise
, ist es frei, die Aufrufe zu _controlfp_s
ignorieren. Wenn Sie beispielsweise sowohl die x86-Architektur als auch /O2
/fp:precise
die x86-Architektur kompiliert haben, werden die Grenzen nicht berechnet, und die Beispielprogrammausgabe wird ausgegeben:
cLower = -inf
cUpper = -inf
Bei der Kompilierung mithilfe sowohl der x86-Architektur als auch /O2
/fp:strict
der x86-Architektur gibt das Beispielprogramm Folgendes aus:
cLower = -inf
cUpper = -3.40282e+38
Gleitkomma-Sonderwerte
Unter /fp:precise
- und /fp:strict
, Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, verhalten sich gemäß den IEEE-754-Spezifikationen. Unter /fp:fast
, das Verhalten dieser speziellen Werte kann mit IEEE-754 inkonsistent sein.
In diesem Beispiel wird das unterschiedliche Verhalten spezieller Werte unter /fp:precise
, /fp:strict
und /fp:fast
:
// fp_special_values.cpp
#include <stdio.h>
#include <cmath>
float gf0 = -0.0;
int main()
{
float f1 = INFINITY;
float f2 = NAN;
float f3 = -INFINITY;
bool a, b;
float c, d, e;
a = (f1 == f1);
b = (f2 == f2);
c = (f1 - f1);
d = (f2 - f2);
e = (gf0 / f3);
printf("INFINITY == INFINITY : %d\n", a);
printf("NAN == NAN : %d\n", b);
printf("INFINITY - INFINITY : %f\n", c);
printf("NAN - NAN : %f\n", d);
printf("std::signbit(-0.0/-INFINITY): %d\n", std::signbit(e));
return 0;
}
Bei der Kompilierung mithilfe /O2 /fp:precise
oder /O2 /fp:strict
für die x86-Architektur entsprechen die Ausgaben der IEEE-754-Spezifikation:
INFINITY == INFINITY : 1
NAN == NAN : 0
INFINITY - INFINITY : -nan(ind)
NAN - NAN : nan
std::signbit(-0.0/-INFINITY): 0
Bei der Kompilierung mithilfe /O2 /fp:fast
von ** für die x86-Architektur sind die Ausgaben nicht mit IEEE-754 konsistent:
INFINITY == INFINITY : 1
NAN == NAN : 1
INFINITY - INFINITY : 0.000000
NAN - NAN : 0.000000
std::signbit(-0.0/-INFINITY): 0
Algebraische Gleitkommatransformationen
Unter /fp:precise
und /fp:strict
, der Compiler führt keine mathematische Transformation durch, es sei denn, die Transformation wird garantiert ein bitweise identisches Ergebnis erzeugen. Der Compiler kann solche Transformationen unter /fp:fast
. Beispielsweise kann der Ausdruck a * b + a * c
in der Beispielfunktion algebraic_transformation
in der /fp:fast
Folgenden kompiliert a * (b + c)
werden. Solche Transformationen werden nicht unter /fp:precise
oder /fp:strict
, und der Compiler generiert a * b + a * c
.
float algebraic_transformation (float a, float b, float c)
{
return a * b + a * c;
}
Explizite Gleitkomma-Umwandlungspunkte
Unter /fp:precise
und /fp:strict
, der Compiler rundet auf die Quellcodegenauigkeit an vier bestimmten Punkten während der Ausdrucksauswertung: bei Zuordnungen, Typecasts, wenn Gleitkommaargumente an einen Funktionsaufruf übergeben werden, und wenn ein Funktionsaufruf einen Gleitkommawert zurückgibt. Typecasts können zum expliziten Runden von Zwischenberechnungen verwendet werden. Der /fp:fast
Compiler generiert an diesen Punkten keine expliziten Umwandlungen, um die Genauigkeit des Quellcodes zu gewährleisten. In diesem Beispiel wird das Verhalten unter verschiedenen /fp
Optionen veranschaulicht:
float casting(float a, float b)
{
return 5.0*((double)(a+b));
}
Bei der Kompilierung mithilfe /O2 /fp:precise
oder /O2 /fp:strict
können Sie sehen, dass explizite Typ casts sowohl am Typecast als auch am Funktionsrücklaufpunkt im generierten Code für die x64-Architektur eingefügt werden:
addss xmm0, xmm1
cvtss2sd xmm0, xmm0
mulsd xmm0, QWORD PTR __real@4014000000000000
cvtsd2ss xmm0, xmm0
ret 0
Unter /O2 /fp:fast
dem generierten Code wird vereinfacht, da alle Typ casts weg optimiert sind:
addss xmm0, xmm1
mulss xmm0, DWORD PTR __real@40a00000
ret 0
So legen Sie diese Compileroption in der Visual Studio-Entwicklungsumgebung fest
Öffnen Sie das Dialogfeld Eigenschaftenseiten des Projekts. Weitere Informationen erhalten Sie unter Set C++ compiler and build properties in Visual Studio (Festlegen der Compiler- und Buildeigenschaften (C++) in Visual Studio).
Wählen Sie die Eigenschaftenseite Konfigurationseigenschaften>C/C++>Codegenerierung aus.
Ändern Sie die Gleitkommamodelleigenschaft .
So legen Sie diese Compileroption programmgesteuert fest
- Siehe floatingPointModel.
Siehe auch
MSVC-Compileroptionen
Syntax für die MSVC-Compilerbefehlszeile