/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 != xtrue と評価されます。 /fp:precise では、浮動小数点数の縮約は既定では生成されません。 この動作は、Visual Studio 2022 での新機能です。 以前のバージョンのコンパイラは、/fp:precise が指定されると既定で縮約を生成できました。

コンパイラは、変換によりビット単位で同一の結果が生成されることを保証できる場合を除き、浮動小数点式に対して代数変換を実行しません (再結合や分配など)。 特殊な値 (NaN、+infinity、-infinity、-0.0) を含む式は、IEEE-754 仕様に従って処理されます。 たとえば、x が NaN の場合、x != xtrue と評価されます。 /fp:precise を指定すると、浮動小数点数の縮約が生成される場合があります。

コンパイラは、既定の浮動小数点環境での実行を意図したコードを生成します。 また、浮動小数点環境が実行時にアクセスまたは変更されないことも想定されます。 つまり、コードに関しては、浮動小数点例外のマスクを維持すること、浮動小数点状態レジスタの読み取りまたは書き込みを行わないこと、丸めモードを変更しないことが想定されています。

作成する浮動小数点コードが、浮動小数点ステートメントでの演算や式の順序に依存していない場合 (たとえば、a * b + a * c(b + c) * a として、または 2 * aa + a として計算されるかどうかを気にしない場合) は、より高速で効率的なコードを生成できる /fp:fast オプションを検討します。 作成するコードが、演算と式の順序に依存し、かつ、浮動小数点環境にアクセスしたりそれを変更したりする (たとえば、丸めモードを変更したり、浮動小数点例外をトラップしたりする) 場合は、/fp:strict を使用します。

/fp:strict

/fp:strict の動作は /fp:precise に似ています。つまり、コンパイラは、ターゲット コンピューター用のオブジェク トコードを生成して最適化するときに、ソースの順序と浮動小数点コードの丸めプロパティを保持し、特別な値を処理するときは標準に準拠します。 また、プログラムは、実行時に浮動小数点環境に安全にアクセスしたり、それを変更したりすることもできます。

/fp:strict を指定すると、浮動小数点例外のマスク解除、浮動小数点状態レジスタの読み取りや書き込み、または丸めモードの変更を、プログラムで安全に行うことができるコードが、コンパイラによって生成されます。 コンパイラは、式の評価の間に、代入、型キャスト、浮動小数点引数が関数呼び出しに渡されるとき、および関数呼び出しが浮動小数点値を返すときの、4 つの特定のポイントにおいて、ソース コードの有効桁数への丸めを行います。 中間計算は、コンピューターの精度で実行される場合があります。 型キャストを使用して、中間計算を明示的に丸めることができます。 コンパイラは、変換によりビット単位で同一の結果が生成されることを保証できる場合を除き、浮動小数点式に対して代数変換を行いません (再結合や分配など)。 特殊な値 (NaN、+infinity、-infinity、-0.0) を含む式は、IEEE-754 仕様に従って処理されます。 たとえば、x が NaN の場合、x != xtrue と評価されます。 /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_controlfenv_accessfp_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) に設定され、非正規値が維持され、floatdoublelong 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 開発環境でこのコンパイラ オプションを設定するには

  1. プロジェクトの [プロパティ ページ] ダイアログ ボックスを開きます。 詳細については、Visual Studio での C++ コンパイラとビルド プロパティの設定に関する記事を参照してください。

  2. [構成プロパティ]>[C/C++]>[コード生成] プロパティ ページを選択します。

  3. [浮動小数点モデル] プロパティを変更します。

このコンパイラ オプションをコードから設定するには

関連項目

MSVC コンパイラ オプション
MSVC コンパイラのコマンド ライン構文