web-dev-qa-db-ja.com

C++でPI定数を使用する方法

私はいくつかのC++プログラムでPI定数と三角関数を使いたい。三角関数はinclude <math.h>で得られます。ただし、このヘッダーファイルにはPIの定義はありません。

手動で定義せずにPIを入手する方法を教えてください。

404
Etan

いくつかの(特に古い)プラットフォームでは(下記のコメントを参照)あなたがする必要があるかもしれません

#define _USE_MATH_DEFINES

そして必要なヘッダファイルをインクルードします。

#include <math.h>

そしてpiの値は次のようにしてアクセスできます。

M_PI

私のmath.h(2014)では、次のように定義されています。

# define M_PI           3.14159265358979323846  /* pi */

しかし、もっとあなたのmath.hをチェックしてください。 "古い" math.hからの抜粋(2009年):

/* Define _USE_MATH_DEFINES before including math.h to expose these macro
 * definitions for common math constants.  These are placed under an #ifdef
 * since these commonly-defined names are not part of the C/C++ standards.
 */

しかしながら:

  1. 新しいプラットフォームでは(少なくとも私の64ビットUbuntu 14.04では)私は_USE_MATH_DEFINESを定義する必要はありません。

  2. (最近の)Linuxプラットフォームでは、GNU Extensionとして提供されるlong double値もあります。

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */
    
477
Ferenc Deak

Piはatan(1)*4として計算できます。このようにして値を計算し、それをキャッシュに入れることができます。

162
Konamiman

Boostを使用することもできます。これは、要求された型に対して最大の精度で重要な数学定数を定義するものです(例:float vs double)。

const double pi = boost::math::constants::pi<double>();

より多くの例については boostのドキュメント をチェックしてください。

107
BuschnicK

代わりにチップ上のFPUユニットから入手してください。

double get_PI()
{
    double pi;
    __asm
    {
        fldpi
        fstp pi
    }
    return pi;
}

double PI = get_PI();
63
Henrik

私はあなたが必要とする精度にただpiをタイプインすることをお勧めします。これはあなたの実行に計算時間を追加しないでしょう、そしてそれは少しのヘッダーも#defineも使用せずに移植可能です。 acosまたはatanの計算は、事前計算された値を使用するよりも常に高価です。

const double PI  =3.141592653589793238463;
const float  PI_F=3.14159265358979f;
47
Alex

書くよりも

#define _USE_MATH_DEFINES

コンパイラに応じて-D_USE_MATH_DEFINESまたは/D_USE_MATH_DEFINESを使用することをお勧めします。

こうすることで、ヘッダを含める前に(#defineを付けずに)誰かがイベントを起こしたとしても、不明瞭なコンパイラエラーの代わりに定数を使用することになります。

42
Matthieu M.

公式の標準ライブラリは定数PIを定義していないので、あなたはそれを自分で定義しなければならないでしょう。それでは、「手動で定義しなくてもPIを取得するにはどうすればよいですか」というあなたの質問に対する答えがわかります。 「あなたはそうではありません - あるいは、コンパイラ固有の拡張機能に頼っています」。移植性を気にしないのであれば、コンパイラのマニュアルをチェックしてください。

C++では、書くことができます

const double PI = std::atan(1.0)*4;

しかし、この定数の初期化は静的であるという保証はありません。しかし、G ++コンパイラはこれらの数学関数を組み込み関数として扱い、コンパイル時にこの定数式を計算できます。

38
sellibitze

Math.hの Posixのマニュアルページから

   The  <math.h>  header  shall  provide for the following constants.  The
   values are of type double and are accurate within the precision of  the
   double type.

   M_PI   Value of pi

   M_PI_2 Value of pi/2

   M_PI_4 Value of pi/4

   M_1_PI Value of 1/pi

   M_2_PI Value of 2/pi

   M_2_SQRTPI
          Value of 2/ sqrt pi
29
Joakim

標準C++にはPIの定数はありません。

多くのC++コンパイラは、cmath(またはCの場合はM_PI)にmath.hを標準外の拡張子として定義しています。表示する前に#define _USE_MATH_DEFINESする必要があります。

24
RichieHindle

私はやります

template<typename T>
T const pi = std::acos(-T(1));

または

template<typename T>
T const pi = std::arg(-std::log(T(2)));

あなたが必要とする精度でπをタイプする _ではないでしょう。それはどういう意味でもあると思いますか? 必要な精度Tの精度ですが、Tについては何も知りません。

Tfloatdoubleまたはlong doubleになります。したがって、long doubleの精度を入力するだけです

template<typename T>
T const pi = static_cast<T>(/* long double precision π */);

しかし、将来的にはlong doubleよりもさらに高い精度を持つ新しい浮動小数点型が標準に含まれないことを本当に知っていますか?あなたは違います。

そしてそれが最初の解決策が美しい理由です。あなたは、規格が新しい型の三角関数をオーバーロードするだろうということをかなり確かにすることができます。

そして、初期化時の三角関数の評価がパフォーマンス上のペナルティであるとは言わないでください。

14
0xbadf00d

私はすべての基盤をカバーするプロジェクトの私の共通のヘッダーの1つで以下を使います:

#define _USE_MATH_DEFINES
#include <cmath>

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

#ifndef M_PIl
#define M_PIl (3.14159265358979323846264338327950288)
#endif

ちなみに<cmath>をインクルードした場合、以下のコンパイラはすべてM_PIおよびM_PIl定数を定義します。 VC++にのみ必要な `#define _USE_MATH_DEFINESを追加する必要はありません。

x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+
8
Shital Shah

すべての実装がそれをあなたに提供するわけではないので、私は一般的に自分自身で定義することを好みます:const double PI = 2*acos(0.0);

この関数が実行時に呼び出されるのか、コンパイル時に静的に呼び出されるのかという問題は、通常は問題にはなりません。

8
Sumudu Fernando

この記事 by Danny Kalev C++ 14以降のための素晴らしいヒントがあります。

template<typename T>
constexpr T pi = T(3.1415926535897932385);

私はこれがかなりクールだと思いました(私ができる限り最高の精度のPIを使うことができますが)、特にテンプレートが型に基づいてそれを使うことができるので。

template<typename T>
T circular_area(T r) {
  return pi<T> * r * r;
}
double darea= circular_area(5.5);//uses pi<double>
float farea= circular_area(5.5f);//uses pi<float>
5
Beta Jester

M_PI、M_PI_2、M_PI_4などの値は標準のC++ではないため、constexprがより良い解決策のようです。同じpiを計算するために異なるconst式を定式化することができ、それらが(すべて)完全な精度を提供するかどうかが問題になります。 C++標準では、piの計算方法については明示的に言及されていません。したがって、私は手動でpiを定義することに頼る傾向があります。私は以下の解決策を共有したいと思います。それはπのあらゆる種類の分数を完全な精度でサポートします。

#include <ratio>
#include <iostream>

template<typename RATIO>
constexpr double dpipart()
{
    long double const pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899863;
    return static_cast<double>(pi * RATIO::num / RATIO::den);
}

int main()
{
    std::cout << dpipart<std::ratio<-1, 6>>() << std::endl;
}
4

C++ 20 std::numbers::pi

ついに到着しました: http://eel.is/c++draft/numbers

私は使用法が次のようになることを期待しています:

#include <numbers>
#include <iostream>

int main() {
    std::cout << std::numbers::pi << std::endl;
}

GCCにサポートが届いたら試してみます。GCC9.1.0のg++-9 -std=c++2aはまだサポートしていません。

受け入れられた提案は次のとおりです。

5.0。 「ヘッダー」[ヘッダー]テーブル[tab:cpp.library.headers]で、新しい<math>ヘッダーを追加する必要があります。

[...]

namespace std {
namespace math { 
  template<typename T > inline constexpr T pi_v = unspecified;
    inline constexpr double pi = pi_v<double>;

もちろんstd::numbers::eもあります:-) C++でオイラー定数またはオイラーを計算する方法

これらの定数は、C++ 14変数テンプレート機能を使用します。 C++ 14変数テンプレート:目的は何ですか?使用例は?

ドラフトの以前のバージョンでは、定数はstd::math::piの下にありました。 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf =

C++ 14ではstatic constexpr auto pi = acos(-1);を実行できます

2
Willy Goat

Windows(cygwin + g ++)では、-D_XOPEN_SOURCE=500M_PIの定義を処理するためにプリプロセッサ用のフラグmath.hを追加する必要があることがわかりました。

2
Papa Smurf

あなたはこれを行うことができます:

#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

M_PIが既にcmathに定義されている場合、これはcmathを含めること以外に何もしません。 M_PIが定義されていない場合(Visual Studioの場合など)、それが定義されます。どちらの場合も、piの値を取得するためにM_PIを使用できます。

Piのこの値はQt Creatorのqmath.hから来ています。

1
Donald Duck

いくつかの優雅な解決策。三角関数の精度が型の精度と同じであることに疑問があります。定数値を書くことを好む人のために、これはg ++のために働く: -

template<class T>
class X {
public:
            static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}

256桁の10進数の精度は、将来のlong long long double型には十分です。もっと必要な場合は https://www.piday.org/million/ にアクセスしてください。

0
Jon Guiton