私はいくつかのC++プログラムでPI定数と三角関数を使いたい。三角関数はinclude <math.h>
で得られます。ただし、このヘッダーファイルにはPIの定義はありません。
手動で定義せずにPIを入手する方法を教えてください。
いくつかの(特に古い)プラットフォームでは(下記のコメントを参照)あなたがする必要があるかもしれません
#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.
*/
しかしながら:
新しいプラットフォームでは(少なくとも私の64ビットUbuntu 14.04では)私は_USE_MATH_DEFINES
を定義する必要はありません。
(最近の)Linuxプラットフォームでは、GNU Extensionとして提供されるlong double
値もあります。
# define M_PIl 3.141592653589793238462643383279502884L /* pi */
Piはatan(1)*4
として計算できます。このようにして値を計算し、それをキャッシュに入れることができます。
Boostを使用することもできます。これは、要求された型に対して最大の精度で重要な数学定数を定義するものです(例:float vs double)。
const double pi = boost::math::constants::pi<double>();
より多くの例については boostのドキュメント をチェックしてください。
代わりにチップ上のFPUユニットから入手してください。
double get_PI()
{
double pi;
__asm
{
fldpi
fstp pi
}
return pi;
}
double PI = get_PI();
私はあなたが必要とする精度にただpiをタイプインすることをお勧めします。これはあなたの実行に計算時間を追加しないでしょう、そしてそれは少しのヘッダーも#defineも使用せずに移植可能です。 acosまたはatanの計算は、事前計算された値を使用するよりも常に高価です。
const double PI =3.141592653589793238463;
const float PI_F=3.14159265358979f;
書くよりも
#define _USE_MATH_DEFINES
コンパイラに応じて-D_USE_MATH_DEFINES
または/D_USE_MATH_DEFINES
を使用することをお勧めします。
こうすることで、ヘッダを含める前に(#defineを付けずに)誰かがイベントを起こしたとしても、不明瞭なコンパイラエラーの代わりに定数を使用することになります。
公式の標準ライブラリは定数PIを定義していないので、あなたはそれを自分で定義しなければならないでしょう。それでは、「手動で定義しなくてもPIを取得するにはどうすればよいですか」というあなたの質問に対する答えがわかります。 「あなたはそうではありません - あるいは、コンパイラ固有の拡張機能に頼っています」。移植性を気にしないのであれば、コンパイラのマニュアルをチェックしてください。
C++では、書くことができます
const double PI = std::atan(1.0)*4;
しかし、この定数の初期化は静的であるという保証はありません。しかし、G ++コンパイラはこれらの数学関数を組み込み関数として扱い、コンパイル時にこの定数式を計算できます。
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
標準C++にはPIの定数はありません。
多くのC++コンパイラは、cmath
(またはCの場合はM_PI
)にmath.h
を標準外の拡張子として定義しています。表示する前に#define _USE_MATH_DEFINES
する必要があります。
私はやります
template<typename T>
T const pi = std::acos(-T(1));
または
template<typename T>
T const pi = std::arg(-std::log(T(2)));
あなたが必要とする精度でπをタイプする _ではないでしょう。それはどういう意味でもあると思いますか? 必要な精度はT
の精度ですが、T
については何も知りません。
T
はfloat
、double
またはlong double
になります。したがって、long double
の精度を入力するだけです
template<typename T>
T const pi = static_cast<T>(/* long double precision π */);
しかし、将来的にはlong double
よりもさらに高い精度を持つ新しい浮動小数点型が標準に含まれないことを本当に知っていますか?あなたは違います。
そしてそれが最初の解決策が美しい理由です。あなたは、規格が新しい型の三角関数をオーバーロードするだろうということをかなり確かにすることができます。
そして、初期化時の三角関数の評価がパフォーマンス上のペナルティであるとは言わないでください。
私はすべての基盤をカバーするプロジェクトの私の共通のヘッダーの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+
すべての実装がそれをあなたに提供するわけではないので、私は一般的に自分自身で定義することを好みます:const double PI = 2*acos(0.0);
。
この関数が実行時に呼び出されるのか、コンパイル時に静的に呼び出されるのかという問題は、通常は問題にはなりません。
この記事 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>
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;
}
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);
を実行できます
Windows(cygwin + g ++)では、-D_XOPEN_SOURCE=500
のM_PI
の定義を処理するためにプリプロセッサ用のフラグmath.h
を追加する必要があることがわかりました。
あなたはこれを行うことができます:
#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から来ています。
いくつかの優雅な解決策。三角関数の精度が型の精度と同じであることに疑問があります。定数値を書くことを好む人のために、これは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/ にアクセスしてください。