/fp
(浮動小数点に関する動作の指定)
コンパイラによる浮動小数点式、最適化、例外の処理方法を指定します。 /fp
オプションでは、丸めモード、例外マスク、非正規動作に対する浮動小数点環境の変更を生成されるコードで許可するかどうか、および浮動小数点状態チェックから現在の正確な結果を返すかどうかを指定します。 これによって、コンパイラで次の 2 種類のうちどちらのコードを生成するかを制御します。1 つは、ソースの操作と式の順序を維持し、NaN 伝達の標準に準拠するコードです。 もう 1 つは、操作を並べ替えたり結合したり、IEEE-754 標準で許可されていない簡略化代数変換を使用したりできる、より効率的なコードです。
構文
/fp:contract
$
/fp:fast
/fp:precise
/fp:strict
$
/fp:fast
/fp:precise
/fp:strict
引数
/fp:contract
/fp:contract
オプションを使用すると、/fp:precise
および /fp:except
オプションが指定されたときにコンパイラは浮動小数点数の縮約を生成できます。 "縮約" は、Fused-Multiply-Add (FMA) など、浮動小数点演算を結合する機械命令です。 IEEE-754 で基本演算として定義されている FMA は、加算の前に途中の積を丸めないため、結果は乗算と加算を個別に行う場合と異なる可能性があります。 1 つの命令として実装されているため、個別の命令より高速な場合があります。 速度と引き換えに、ビットごとの正確な結果が犠牲になり、中間値を調べることもできません。
既定では、/fp:fast
オプションによって /fp:contract
が有効になります。 /fp:contract
オプションは、/fp:strict
と互換性がありません。
/fp:contract
オプションは、Visual Studio 2022 の新機能です。
/fp:precise
コンパイラでは既定で /fp:precise
動作が使用されます。
/fp:precise
では、コンパイラは、ターゲット コンピューター用のオブジェク トコードを生成して最適化するときに、ソース式の順序と浮動小数点コードの丸めプロパティを保持します。 コンパイラは、式の評価の間に、代入、型キャスト、浮動小数点引数が関数呼び出しに渡されるとき、および関数呼び出しが浮動小数点値を返すときの、4 つの特定のポイントにおいて、ソース コードの有効桁数への丸めを行います。 中間計算は、コンピューターの精度で実行される場合があります。 型キャストを使用して、中間計算を明示的に丸めることができます。
コンパイラは、変換によりビット単位で同一の結果が生成されることを保証できる場合を除き、浮動小数点式に対して代数変換を実行しません (再結合や分配など)。 特殊な値 (NaN、+infinity、-infinity、-0.0) を含む式は、IEEE-754 仕様に従って処理されます。 たとえば、x
が NaN の場合、x != x
は true
と評価されます。 /fp:precise
では、浮動小数点数の縮約は既定では生成されません。 この動作は、Visual Studio 2022 での新機能です。 以前のバージョンのコンパイラは、/fp:precise
が指定されると既定で縮約を生成できました。
コンパイラは、変換によりビット単位で同一の結果が生成されることを保証できる場合を除き、浮動小数点式に対して代数変換を実行しません (再結合や分配など)。 特殊な値 (NaN、+infinity、-infinity、-0.0) を含む式は、IEEE-754 仕様に従って処理されます。 たとえば、x
が NaN の場合、x != x
は true
と評価されます。 /fp:precise
を指定すると、浮動小数点数の縮約が生成される場合があります。
コンパイラは、既定の浮動小数点環境での実行を意図したコードを生成します。 また、浮動小数点環境が実行時にアクセスまたは変更されないことも想定されます。 つまり、コードに関しては、浮動小数点例外のマスクを維持すること、浮動小数点状態レジスタの読み取りまたは書き込みを行わないこと、丸めモードを変更しないことが想定されています。
作成する浮動小数点コードが、浮動小数点ステートメントでの演算や式の順序に依存していない場合 (たとえば、a * b + a * c
が (b + c) * a
として、または 2 * a
が a + a
として計算されるかどうかを気にしない場合) は、より高速で効率的なコードを生成できる /fp:fast
オプションを検討します。 作成するコードが、演算と式の順序に依存し、かつ、浮動小数点環境にアクセスしたりそれを変更したりする (たとえば、丸めモードを変更したり、浮動小数点例外をトラップしたりする) 場合は、/fp:strict
を使用します。
/fp:strict
/fp:strict
の動作は /fp:precise
に似ています。つまり、コンパイラは、ターゲット コンピューター用のオブジェク トコードを生成して最適化するときに、ソースの順序と浮動小数点コードの丸めプロパティを保持し、特別な値を処理するときは標準に準拠します。 また、プログラムは、実行時に浮動小数点環境に安全にアクセスしたり、それを変更したりすることもできます。
/fp:strict
を指定すると、浮動小数点例外のマスク解除、浮動小数点状態レジスタの読み取りや書き込み、または丸めモードの変更を、プログラムで安全に行うことができるコードが、コンパイラによって生成されます。 コンパイラは、式の評価の間に、代入、型キャスト、浮動小数点引数が関数呼び出しに渡されるとき、および関数呼び出しが浮動小数点値を返すときの、4 つの特定のポイントにおいて、ソース コードの有効桁数への丸めを行います。 中間計算は、コンピューターの精度で実行される場合があります。 型キャストを使用して、中間計算を明示的に丸めることができます。 コンパイラは、変換によりビット単位で同一の結果が生成されることを保証できる場合を除き、浮動小数点式に対して代数変換を行いません (再結合や分配など)。 特殊な値 (NaN、+infinity、-infinity、-0.0) を含む式は、IEEE-754 仕様に従って処理されます。 たとえば、x
が NaN の場合、x != x
は true
と評価されます。 /fp:strict
を指定すると、浮動小数点数の縮約は生成されません。
コンパイラは、例外をトラップし、プログラムが実行時に浮動小数点環境にアクセスまたは変更できるようにするために、余分な命令を挿入する必要があるため、/fp:precise
より /fp:strict
の方が計算にかかる負荷が大きくなります。 コードが、この機能を使用していなくても、ソース コードの順序や丸め処理を必要とする場合、または特殊な値に依存する場合は、/fp:precise
を使用します。 そうでない場合は、いっそう速くて小さいコードを生成できる、/fp:fast
の使用を検討します。
/fp:fast
/fp:fast
オプションを使用すると、コンパイラは、浮動小数点演算の順序変更、結合、または簡略化を行い、速度と領域に関して浮動小数点コードを最適化することができます。 コンパイラは、代入ステートメント、型キャスト、または関数呼び出しでの丸め処理を省略することがあります。 結合法則や分配法則などを使用して、演算を並べ替えたり、代数変換を行ったりすることがあります。 そのような変換によって著しく異なる丸め動作になる場合であっても、コードの順序を変更する可能性があります。 この強化された最適化により、一部の浮動小数点計算の結果が、他の /fp
オプションによって生成されるものと異なる場合があります。 特殊な値 (NaN、+infinity、-infinity、-0.0) は、伝達されない場合、または IEEE-754 標準に厳密に従って動作しない場合があります。 /fp:fast
を指定すると、浮動小数点数の縮約が生成される場合があります。 /fp:fast
では、コンパイラはやはり基になるアーキテクチャによってバインドされています。また、/arch
オプションを使用することにより、より多くの最適化を利用できます。
/fp:fast
では、コンパイラは既定の浮動小数点環境での実行を意図したコードを生成し、浮動小数点環境が実行時にアクセスまたは変更されないと想定します。 つまり、コードに関しては、浮動小数点例外のマスクを維持すること、浮動小数点状態レジスタの読み取りまたは書き込みを行わないこと、丸めモードを変更しないことが想定されています。
/fp:fast
は、ソース コードでの浮動小数点式の厳密な順序と丸めを必要とせず、NaN
などの特別な値の処理を標準の規則に依存しないプログラムのためのものです。 作成する浮動小数点コードが、ソース コードの順序と丸めの維持を必要とする場合、または特殊な値の標準の動作に依存するる場合は、/fp:precise
を使用します。 丸めモードを変更したり、浮動小数点例外をマスク解除したり、浮動小数点の状態をチェックしたりするために、コードが浮動小数点環境にアクセスしたりそれを変更したりする場合は、/fp:strict
を使用します。
/fp:except
/fp:except
オプションを指定すると生成されるコードでは、マスクされていない浮動小数点例外は発生した正確な位置で生成され、他の浮動小数点例外は発生しません。 既定では、/fp:strict
オプションを指定すると /fp:except
が有効になり、/fp:precise
を指定すると有効になりません。 /fp:except
オプションは、/fp:fast
と互換性がありません。 このオプションは、/fp:except-
を使用することで明示的に無効にすることができます。
/fp:except
だけでは、浮動小数点例外は有効になりません。 しかし、プログラムで浮動小数点例外を有効にするためには必要です。 浮動小数点例外を有効にする方法について詳しくは、_controlfp
に関する記事をご覧ください。
解説
同じコンパイラ コマンド ラインで、複数の /fp
オプションを指定できます。 一度に有効にできるオプションは、/fp:strict
、/fp:fast
、/fp:precise
のうちの 1 つだけです。 コマンド ラインで複数のオプションを指定すると、後にあるオプションが優先され、コンパイラによって警告が生成されます。 /fp:strict
および /fp:except
オプションは、/clr
と互換性がありません。
/Za
(ANSI 互換) オプションは、/fp
と互換性がありません。
コンパイラ ディレクティブを使用した浮動小数点動作の制御
コンパイラには、コマンドラインで指定された浮動小数点動作をオーバーライドするために、float_control
、fenv_access
、fp_contract
の 3 つの pragma ディレクティブが用意されています。 これらのディレクティブを使用すると、関数内ではなく、関数レベルで浮動小数点動作を制御できます。 これらのディレクティブは、/fp
オプションに直接には対応していません。 次の表では、/fp
のオプションと pragma ディレクティブの相互の対応を示します。 詳しくは、個々のオプションと pragma ディレクティブのドキュメントをご覧ください。
オプション | 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 |
* Visual Studio 2022 より前の Visual Studio のバージョンでは、/fp:precise
の既定の動作は fp_contract(on)
です。
オプション | 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 |
* Visual Studio 2022 以降の Visual Studio のバージョンでは、/fp:precise
の既定の動作は fp_contract(off)
です。
浮動小数点の既定の環境
プロセスが初期化されるときに、"既定の浮動小数点環境" が設定されます。 この環境では、すべての浮動小数点例外がマスクされ、丸めモードが "最も近い値への丸め" (FE_TONEAREST
) に設定され、非正規値が維持され、float
、double
、long double
値に対して仮数部の既定の精度が使用され、サポートされている場合は無限大制御が既定のアフィン モードに設定されます。
浮動小数点環境へのアクセスと変更
Microsoft Visual C++ ランタイムには、浮動小数点環境にアクセスして変更するための関数がいくつか用意されています。 これには、_controlfp
、_clearfp
、_statusfp
とこれらのバリエーションが含まれます。 コードで浮動小数点環境にアクセスしたり変更したりしたときにプログラムが正しく動作するためには、これらの関数が有効になるように、/fp:strict
オプションまたは fenv_access
プラグマを使用して、fenv_access
を有効にする必要があります。 fenv_access
が有効になっていない場合、浮動小数点環境のアクセスまたは変更によって、予期しないプログラムの動作が発生する可能性があります。
コードは、浮動小数点環境に対して要求された変更を行わない可能性があります。
浮動小数点の状態レジスタは、予期される結果や現在の結果を報告しない場合があります。
予期しない浮動小数点例外が発生したり、予期される浮動小数点例外が発生しない可能性があります。
コードが浮動小数点環境にアクセスしたり変更したりする場合、fenv_access
が有効になっているコードと fenv_access
が有効になっていないコードを結合するときは注意する必要があります。 fenv_access
が有効になっていないコードでは、コンパイラはプラットフォームの既定の浮動小数点環境が有効であると想定します。 また、浮動小数点の状態がアクセスまたは変更されないことも想定します。 fenv_access
が有効になっていない関数に制御が移る前に、ローカルの浮動小数点環境を保存し、既定の状態に復元することをお勧めします。 この例では、float_control
pragma を設定および復元する方法を示します。
#pragma float_control(precise, on, push)
// Code that uses /fp:strict mode
#pragma float_control(pop)
浮動小数点数の丸めモードの制御
/fp:precise
および /fp:fast
を指定すると、コンパイラは既定の浮動小数点環境での実行を意図したコードを生成します。 実行時に環境のアクセスまたは変更は行われないものと想定されます。 つまり、コンパイラは、コードが浮動小数点例外のマスクを解除したり、浮動小数点状態レジスタの読み取りや書き込みを行ったり、丸めモードを変更したりしないものと想定します。 ただし、プログラムによっては、浮動小数点環境の変更が必要になります。 たとえば、このサンプルでは、浮動小数点数の丸めモードを変更して、浮動小数点乗算のエラー境界を計算します。
// 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;
}
/fp:fast
と /fp:precise
では、コンパイラは既定の浮動小数点環境を想定するので、_controlfp_s
呼び出しを無視しても問題は発生しません。 たとえば、x86 アーキテクチャで /O2
と /fp:precise
の両方を使用してコンパイルした場合、境界は計算されず、サンプル プログラムは次のように出力します。
cLower = -inf
cUpper = -inf
x86 アーキテクチャで /O2
と /fp:strict
の両方を使用してコンパイルすると、サンプル プログラムは次のように出力します。
cLower = -inf
cUpper = -3.40282e+38
浮動小数点の特殊な値
/fp:precise
と /fp:strict
では、特殊な値 (NaN、+infinity、-infinity、-0.0) を含む式は、IEEE-754 の仕様に従って動作します。 /fp:fast
では、これらの特殊な値の動作が IEEE-754 と異なる可能性があります。
このサンプルでは、/fp:precise
、/fp:strict
、および /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;
}
x86 アーキテクチャを対象に /O2 /fp:precise
または /O2 /fp:strict
を使用してコンパイルすると、出力は IEEE-754 の仕様と一致します。
INFINITY == INFINITY : 1
NAN == NAN : 0
INFINITY - INFINITY : -nan(ind)
NAN - NAN : nan
std::signbit(-0.0/-INFINITY): 0
x86 アーキテクチャを対象に /O2 /fp:fast
** を使用してコンパイルすると、出力は IEEE-754 と一致しません。
INFINITY == INFINITY : 1
NAN == NAN : 1
INFINITY - INFINITY : 0.000000
NAN - NAN : 0.000000
std::signbit(-0.0/-INFINITY): 0
浮動小数点数の代数変換
/fp:precise
と /fp:strict
では、変換によりビット単位で同一の結果が生成されることが保証されない限り、コンパイラは数学的変換を実行しません。 /fp:fast
では、コンパイラはそのような変換を行う場合があります。 たとえば、サンプル関数 algebraic_transformation
の式 a * b + a * c
は、/fp:fast
では a * (b + c)
にコンパイルされる可能性があります。 このような変換は /fp:precise
または /fp:strict
では行われず、コンパイラは a * b + a * c
を生成します。
float algebraic_transformation (float a, float b, float c)
{
return a * b + a * c;
}
浮動小数点の明示的なキャスト ポイント
/fp:precise
と /fp:strict
では、コンパイラは、式の評価の間に、代入、型キャスト、浮動小数点引数が関数呼び出しに渡されるとき、および関数呼び出しが浮動小数点値を返すときの、4 つの特定のポイントにおいて、ソース コードの有効桁数への丸めを行います。 型キャストを使用して、中間計算を明示的に丸めることができます。 /fp:fast
では、コンパイラは、ソース コードの精度を保証するため、これらのポイントで明示的なキャストを生成しません。 このサンプルでは、異なる /fp
オプションでの動作を示します。
float casting(float a, float b)
{
return 5.0*((double)(a+b));
}
/O2 /fp:precise
または /O2 /fp:strict
を使ってコンパイルすると、x64 アーキテクチャ用に生成されるコードの型キャストと関数のリターン ポイントの両方に、明示的な型キャストが挿入されることがわかります。
addss xmm0, xmm1
cvtss2sd xmm0, xmm0
mulsd xmm0, QWORD PTR __real@4014000000000000
cvtsd2ss xmm0, xmm0
ret 0
/O2 /fp:fast
では、すべての型キャストが最適化されるため、生成されるコードは簡単になります。
addss xmm0, xmm1
mulss xmm0, DWORD PTR __real@40a00000
ret 0
Visual Studio 開発環境でこのコンパイラ オプションを設定するには
プロジェクトの [プロパティ ページ] ダイアログ ボックスを開きます。 詳細については、Visual Studio での C++ コンパイラとビルド プロパティの設定に関する記事を参照してください。
[構成プロパティ]>[C/C++]>[コード生成] プロパティ ページを選択します。
[浮動小数点モデル] プロパティを変更します。
このコンパイラ オプションをコードから設定するには
- 以下を参照してください。floatingPointModel