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


476

一部のC ++プログラムでPI定数および三角関数を使用したいと思います。で三角関数を取得しinclude <math.h>ます。ただし、このヘッダーファイルにはPIの定義がないようです。

手動で定義せずにPIを取得するにはどうすればよいですか?


3
@tiwo、あなたは違い何を求めている3.143.141592atan(1) * 4
NikolaMalešević9年

21
C.するためのものである、cmath代わりのmath.hのC ++で使用されるべきであるサイドノートなど
juzzlin

4
大まかに関連:PIの値を定義から直接計算する方法については、cise.ufl.edu /〜manuel / obfuscate / pi.cを参照してください。
lorro

回答:


537

一部の(特に古い)プラットフォーム(以下のコメントを参照)では、次の操作が必要になる場合があります。

#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プラットフォームではlong double、GNU拡張機能として提供されている値もあります。

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */

51
#define _USE_MATH_DEFINESVisual C ++での#include <math.h>定義M_PIが続きます。ありがとう。
Etan、

3
cygwinヘッダーでも動作します。
Rob

24
cmath代わりにいつでも含めることができますmath.h
リチャードJ.ロスIII

10
_USE_MATH_DEFINESGCCが不平を言っているかどうかを定義した後でも、定義が許可されていない__STRICT_ANSI__(おそらく、-pedanticまたは-std=c++11M_PIが定義されているため、それをで定義解除します-D__STRICT_ANSI__。それを自分で定義するとき、それはC ++なので、マクロではなくconstexpr auto M_PI = 3.14159265358979323846;
legends2k 2014年

1
2018年現在、回答は<math.h>ではなく<cmath>を使用するように明確に更新する必要がある
jaskmar

170

Piはとして計算できますatan(1)*4。この方法で値を計算してキャッシュすることができます。


78
c ++ 11ユーザーの場合:constexpr double pi() { return std::atan(1)*4; }
matiu

41
-1:(atan(1)*4 == 3.141592653589793238462643383279502884大まかに)次の場合にのみ機能します。私はそれに賭けません。通常で、生のリテラルを使用して定数を定義します。必要がないときに精度を失うのはなぜですか?
Thomas Eding

29
を使用すると、乗算演算を回避できatan2(0, -1);ます。
legends2k

44
@matiuでatanはありませんconstexpr
R.マルティーニョフェルナンデス

45
acos(-1)代わりに試してくださいatan2
user541686 2014

113

また、ブーストを使用することもできます。ブーストは、要求された型(すなわち、浮動小数点と倍精度)に対して最大の精度で重要な数学定数を定義します。

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

その他の例については、ブーストのドキュメントをご覧ください。


184
ブースト:1999年以来、C ++の不要な複雑さを後押ししています!
Dan Molding

47
キャッチーで一部真実。一方、ブーストは
ときどき

59
@DanMoulding:うーん。他に知っている言語はCだけですか?私が知っている他のすべての言語(Cを除く)には、C ++よりも大きな標準ライブラリ(Python、Haskell、C#、PHP、Delphi、Erlang、Javaなど)があるためです。個人的な経験から、そのエリート主義的not gonna use libs意見は害虫であり、おそらくC ++で書かれた悪いソフトウェアの最大の理由です。
セバスチャンマッハ

11
@Gracchus:うん。ライブラリなし(または新しいC ++ 11ライブラリなし)のC ++は、その言語が好きで、自分ですべてをコーディングしたいのと同じくらい生産性が高くありません。
セバスチャンマッハ

14
私は、サイズではなく複雑さを言ったと思います。おそらくa)3つのネストされた名前空間、およびb)piを通常の定数ではなくテンプレート関数として定義することをおそらく参照します。
Timmmm 2014

83

代わりに、チップ上のFPUユニットから取得します。

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

double PI = get_PI();

40
:-)おそらくそのプラットフォームに依存していませんが、追加のエキゾチックな素晴らしいソリューションです!
Etan

3
私はあなたがここで箱から出してどのようにあなたを愛しています;)
VivienLeger

1
私はこの答えが大好きです。最適化コンパイラーが最新のものほどひどく関与していない最近の小さな流行である古いx86プラットフォームをターゲットにする場合に特に役立ちます。このヘンリックをありがとう!
マット

49

必要な精度でpiを入力することをお勧めします。これは実行に計算時間を追加せず、ヘッダーや#definesを使用せずに移植できます。acosまたはatanの計算は、事前計算された値を使用するよりも常にコストがかかります。

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

28
これは、私たちがこのアプローチを採用してはならない素晴らしい例です。人々は、ミス、丸め、コピー&貼り付けなどを行います。M_PIを使用するのが正しいアプローチだと思います。
nacho4d 2014年

10
C ++ 11でこれを行う場合は、constaを作成しますconstexpr
legends2k 2014年

3
@ nacho4d利用可能であればM_PIを好​​みますが、すべてのシステムがPOSIXに準拠しているわけではありません。M_PIが利用できない場合、このアプローチは4 * atan(1)メソッドよりも優れていると思います。
m24p 2014

2
「acosやatanを計算することは常により高価です」は正しくありません。最新の最適化コンパイラはすべて、標準の数学関数についてすべて知っており、それらを一定に伝播できます。例えば参照goo.gl/BvdJyr
ニモ

2
@Nemo、カウンターの例:godbolt.org/g/DsAern他で述べられているように、現在GCCのみがこれを実行しているようconstexprです。これは、基本的な数学関数をとして宣言しているためと考えられます。
パーカーコーツ

47

書くよりも

#define _USE_MATH_DEFINES

-D_USE_MATH_DEFINESまたはを使用することをお勧めします/D_USE_MATH_DEFINESコンパイラの依存をおします。

このようにすると、ヘッダーを含める前に(#defineを使用せずに)誰かが発生した場合でも、追跡に時間がかかる不明瞭なコンパイラエラーではなく、定数が保持されます。


良いヒント。「あなた」がコンパイル単位である場合、もちろん、何かが含まれる前にマクロが定義されていることを確認できます。しかし、「あなた」がヘッダーファイルである場合、それはあなたのコントロールの外にあります。
スティーブジェソップ

3
実際、「あなた」がコンパイルユニットであっても...ヘッダーの順序に応じて、メンテナンスの悪夢への最短経路です...
Matthieu M.

1
ただし、ヘッダーの順序に依存する必要はありません。ヘッダーを互いに含めるかどうかは関係ありません。ただし、#defineを行う前に#defineを行う場合は、何も含めないでください(少なくとも、何も定義されていないことを前提としています)。同じことがNDEBUGにも当てはまります。
スティーブジェソップ

1
プロジェクトの非常に一般的な問題は、たとえばVisual Studioでコンパイルしている場合、コンパイラーがファイルを処理する順序がわからないため、<cmath>別の場所で使用すると大きな問題になります(特に含まれている別のライブラリに含まれている場合)。彼らがその部分をヘッダーガードの外に置いた方がずっと良かったでしょうが、今はそれについて多くをすることができません。コンパイラー指示文は確かに非常にうまく機能します。
meneldal、

40

公式の標準ライブラリは定数PIを定義していないため、自分で定義する必要があります。したがって、「手動でPIを定義せずにPIを取得するにはどうすればよいですか?」「そうではありません-または、コンパイラ固有の拡張機能に依存しています。」です。移植性について心配していない場合は、コンパイラのマニュアルでこれを確認できます。

C ++を使用すると、

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

ただし、この定数の初期化は静的であるとは限りません。ただし、G ++コンパイラーはこれらの数学関数を組み込み関数として処理し、コンパイル時にこの定数式を計算できます。


6
あなたが言うように、私は通常acos(-1)を使用します。それらはコンパイル時に評価されます。M_PI、acos(-1)、atan(1)* 4をテストしたところ、同じ値が得られました。
ミカ2014

2
従来の方法はを使用すること4*atan(1.)です。atan実装は簡単で、4を掛けることは正確な​​演算です。もちろん、現代のコンパイラは(倍を目指して)必要な精度を持つすべての定数倍、そしてそれが使用することを完全に合理的だacos(-1)としてもまたはstd::abs(std::arg(std::complex<double>(-1.,0.)))オイラーの公式の逆数であるため、より審美的に(私が追加したと思われるよりも楽しませてくれるabsので、私ドン」にt複雑な平面がどのようにカットされるか、またはそれが定義されているかどうかを覚えておいてください)。
tobi_s 2018年

だからといって、あなたが本気だと誤って思った人はいないでしょう(再び__- ')。これはひどい解決策です。atan実装は、その実装を意味する標準によって定義されておらず、おそらくハードウェアに依存しています。これは、数値がひどい場合があることを意味します。つまり、一般的に3.14を使用した方がよい場合があります。さらに、特別な場合でも、かなり遅くなる可能性があります。
midjji

32

math.hのPosix manページから:

   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

3
良い答えですが、リンクは切れています。代わりにこれをお勧めします。
Abderrahim Kitouni 2018

30

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、GCC 9.1.0に到着したら試してみます g++-9 -std=c++2aまだサポートていません。

承認された提案は次のとおりです。

5.0。“ Headers” [headers]テーブル[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::pihttp : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf


27

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

多くのC ++コンパイラは、非標準拡張としてM_PIin cmath(またはmath.hCの場合)を定義しています。あなたが#define _USE_MATH_DEFINESそれを見ることができる前にあなたはしなければならないかもしれません。


18

私はするだろう

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

または

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

必要な精度でπを入力するつもりはありません 。それはどういう意味ですか?あなたが必要とする精度は精度であるが、我々はについて何も知りませんTT

あなたは言うかもしれません:あなたは何について話しているのですか?Tなりますfloatdoubleまたはlong double。したがって、の精度を入力するだけですlong double。つまり、

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

しかし、将来的には、標準でさらに高い精度の新しい浮動小数点型がなくなることを本当に知っていますlong doubleか?あなたはしません。

そして、それが最初のソリューションが美しい理由です。標準が新しいタイプの三角関数をオーバーロードすることを確信できます。

また、初期化時の三角関数の評価がパフォーマンスを低下させるとは言わないでください。


1
arg(log(x)) == πすべてのことに注意してください0 < x < 1
0xbadf00d 2016

これはひどい考えです。タイプごとにオーバーロードされたテンプレートconstexprを使用すると、コンパイルエラーが発生し、新しいタイプが表示された場合に強制的に定義する必要があります。また、trig型は浮動小数点型に限定されないため、一般的にはひどいです。atan(1)の間違いをお楽しみください...標準では、三角関数が実際の三角値を型の精度まで計算することを保証していません。彼らは一般的にはそうしません、そしてそれは例えばfastmathで悪化し、特別な値に対しては常に特に悪いです。
midjji

10

私はすべてのベースをカバーするプロジェクトの私の共通ヘッダーの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

余談ですが、以下のコンパイラはすべて、を含めるとM_PIおよびM_PIl定数を定義します<cmath>。VC ++でのみ必要な `#define _USE_MATH_DEFINESを追加する必要はありません。

x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+

反対投票者はこの回答の何が悪いのかについてコメントできますか?これはよく研究、テストされ、実際のシステムで使用されています。私は間違いがあったらそれを改善したいと思っていました。
Shital Shah

1
参考までに、Borland C ++コンパイラもM_PI必要なしに定義します_USE_MATH_DEFINES
Remy Lebeau

8

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

この関数は実行時に呼び出されるのか、コンパイル時に静的に呼び出されるのかは、通常1回しか発生しないため、問題にはなりません。


8
acos(-1)もpiです。
ロデリックテイラー、

3
多くの場合、メモリの場所からオペランドを読み取るよりも、直接のオペランドをロードする方が、CPU命令やレイテンシが少なくなります。また、事前に計算できるのは、コンパイル時にわかっている式だけです(つまりdouble x = pi * 1.5;、など)。タイトなループのカリカリの数学でPIを使用する場合は、値がコンパイラに認識されていることを確認してください。
Eugene Ryabtsev 2014

7

私はちょうど出くわしたこの記事によるダニーカレブ 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>

4

M_PI、M_PI_2、M_PI_4などの値は標準のC ++ではないため、constexprの方がより良い解決策のようです。同じpiを計算するさまざまなconst式を定式化することができ、それらが(すべて)完全な精度を提供するかどうかが問題になります。C ++標準では、円周率の計算方法について明示的に言及されていません。したがって、私は手動で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;
}

2
非常に素晴らしい。その番号の末尾に「l」または「L」が必要な場合があります。Linuxのコンパイラgccから狭めの警告が表示されます。
Grant Rostig、2019

2

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


2
これは答えではなく、フリットゾーンの答えへのコメントです。
0xbadf00d 2016

2
@ 0xbadf00d:これはM_PI、特定のプラットフォームで作業するために必要な手順を提供する完全にスタンドアロンの回答です。これは、他のプラットフォームに対する回答に対するコメントではなく、他のプラットフォームに対する回答がこのプラットフォームに対するコメントであるということです。
Ben Voigt 2016年

2

C ++ 14を使用すると static constexpr auto pi = acos(-1);


9
std::acosはありませんconstexpr。したがって、コードはコンパイルされません。
0xbadf00d 2016

@ 0xbadf00d g ++でコンパイルしました
Willy Goat

12
@WillyGoat:C ++ 14にacosはないため、g ++は間違っており、C ++ 17にもconstexprなるconstexprことは提案されていません
Ben Voigt

@BenVoigtある数学関数はありconstexprますか?どうやらそうではない:stackoverflow.com/questions/17347935/constexpr-math-functions
wcochran

1
@wcochran:新しいmath関数がたくさんあります。constexpr例をご覧ください(github.com/kthohr/gcem)。ただし、同じ名前のC関数との下位互換性がないため、古い名前を引き継ぐことはできません。
Ben Voigt

2

いくつかのエレガントなソリューション。三角関数の精度が型の精度と等しいことは疑わしいです。定数値を書き込むことを好む人にとって、これはg ++で機能します:-

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

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



1

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

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

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

このpiの値は、Qt Creatorのqmath.hから取得されます。


1

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

#define _USE_MATH_DEFINES // for C++
#include <cmath>

#define _USE_MATH_DEFINES // for C
#include <math.h>

数学定数は、標準C / C ++では定義されていません。それらを使用するには、最初に定義_USE_MATH_DEFINESしてから、cmathまたはを含める必要がありmath.hます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.