一部のC ++プログラムでPI定数および三角関数を使用したいと思います。で三角関数を取得しinclude <math.h>
ます。ただし、このヘッダーファイルにはPIの定義がないようです。
手動で定義せずにPIを取得するにはどうすればよいですか?
一部の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プラットフォームではlong double
、GNU拡張機能として提供されている値もあります。
# define M_PIl 3.141592653589793238462643383279502884L /* pi */
#define _USE_MATH_DEFINES
Visual C ++での#include <math.h>
定義M_PI
が続きます。ありがとう。
cmath
代わりにいつでも含めることができますmath.h
。
_USE_MATH_DEFINES
GCCが不平を言っているかどうかを定義した後でも、定義が許可されていない__STRICT_ANSI__
(おそらく、-pedantic
または-std=c++11
)M_PI
が定義されているため、それをで定義解除します-D__STRICT_ANSI__
。それを自分で定義するとき、それはC ++なので、マクロではなくconstexpr auto M_PI = 3.14159265358979323846;
。
Piはとして計算できますatan(1)*4
。この方法で値を計算してキャッシュすることができます。
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
大まかに)次の場合にのみ機能します。私はそれに賭けません。通常で、生のリテラルを使用して定数を定義します。必要がないときに精度を失うのはなぜですか?
atan2(0, -1);
ます。
atan
はありませんconstexpr
。
acos(-1)
代わりに試してくださいatan2
。
また、ブーストを使用することもできます。ブーストは、要求された型(すなわち、浮動小数点と倍精度)に対して最大の精度で重要な数学定数を定義します。
const double pi = boost::math::constants::pi<double>();
その他の例については、ブーストのドキュメントをご覧ください。
not gonna use libs
意見は害虫であり、おそらくC ++で書かれた悪いソフトウェアの最大の理由です。
代わりに、チップ上のFPUユニットから取得します。
double get_PI()
{
double pi;
__asm
{
fldpi
fstp pi
}
return pi;
}
double PI = get_PI();
必要な精度でpiを入力することをお勧めします。これは実行に計算時間を追加せず、ヘッダーや#definesを使用せずに移植できます。acosまたはatanの計算は、事前計算された値を使用するよりも常にコストがかかります。
const double PI =3.141592653589793238463;
const float PI_F=3.14159265358979f;
const
aを作成しますconstexpr
。
constexpr
です。これは、基本的な数学関数をとして宣言しているためと考えられます。
書くよりも
#define _USE_MATH_DEFINES
-D_USE_MATH_DEFINES
またはを使用することをお勧めします/D_USE_MATH_DEFINES
コンパイラの依存をおします。
このようにすると、ヘッダーを含める前に(#defineを使用せずに)誰かが発生した場合でも、追跡に時間がかかる不明瞭なコンパイラエラーではなく、定数が保持されます。
<cmath>
別の場所で使用すると大きな問題になります(特に含まれている別のライブラリに含まれている場合)。彼らがその部分をヘッダーガードの外に置いた方がずっと良かったでしょうが、今はそれについて多くをすることができません。コンパイラー指示文は確かに非常にうまく機能します。
公式の標準ライブラリは定数PIを定義していないため、自分で定義する必要があります。したがって、「手動でPIを定義せずにPIを取得するにはどうすればよいですか?」「そうではありません-または、コンパイラ固有の拡張機能に依存しています。」です。移植性について心配していない場合は、コンパイラのマニュアルでこれを確認できます。
C ++を使用すると、
const double PI = std::atan(1.0)*4;
ただし、この定数の初期化は静的であるとは限りません。ただし、G ++コンパイラーはこれらの数学関数を組み込み関数として処理し、コンパイル時にこの定数式を計算できます。
4*atan(1.)
です。atan
実装は簡単で、4を掛けることは正確な演算です。もちろん、現代のコンパイラは(倍を目指して)必要な精度を持つすべての定数倍、そしてそれが使用することを完全に合理的だacos(-1)
としてもまたはstd::abs(std::arg(std::complex<double>(-1.,0.)))
オイラーの公式の逆数であるため、より審美的に(私が追加したと思われるよりも楽しませてくれるabs
ので、私ドン」にt複雑な平面がどのようにカットされるか、またはそれが定義されているかどうかを覚えておいてください)。
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 ++ 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::pi
:http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf
私はするだろう
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
か?あなたはしません。
そして、それが最初のソリューションが美しい理由です。標準が新しいタイプの三角関数をオーバーロードすることを確信できます。
また、初期化時の三角関数の評価がパフォーマンスを低下させるとは言わないでください。
arg(log(x)) == π
すべてのことに注意してください0 < x < 1
。
私はすべてのベースをカバーするプロジェクトの私の共通ヘッダーの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+
M_PI
必要なしに定義します_USE_MATH_DEFINES
私は一般的に自分自身を定義することを好みconst double PI = 2*acos(0.0);
ます。すべての実装がそれを提供するわけではないからです。
この関数は実行時に呼び出されるのか、コンパイル時に静的に呼び出されるのかは、通常1回しか発生しないため、問題にはなりません。
double x = pi * 1.5;
、など)。タイトなループのカリカリの数学でPIを使用する場合は、値がコンパイラに認識されていることを確認してください。
私はちょうど出くわしたこの記事によるダニーカレブ 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を定義することにフォールバックする傾向があります。完全な精度でパイのあらゆる種類の分数をサポートする以下の解決策を共有したいと思います。
#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;
}
Windows(cygwin + g ++)では-D_XOPEN_SOURCE=500
、プリプロセッサがM_PI
in の定義を処理するためのフラグを追加する必要があることがわかりましたmath.h
。
M_PI
、特定のプラットフォームで作業するために必要な手順を提供する完全にスタンドアロンの回答です。これは、他のプラットフォームに対する回答に対するコメントではなく、他のプラットフォームに対する回答がこのプラットフォームに対するコメントであるということです。
C ++ 14を使用すると static constexpr auto pi = acos(-1);
std::acos
はありませんconstexpr
。したがって、コードはコンパイルされません。
acos
はないため、g ++は間違っており、C ++ 17にもconstexpr
なるconstexpr
ことは提案されていません
constexpr
ますか?どうやらそうではない:stackoverflow.com/questions/17347935/constexpr-math-functions
constexpr
例をご覧ください(github.com/kthohr/gcem)。ただし、同じ名前のC関数との下位互換性がないため、古い名前を引き継ぐことはできません。
いくつかのエレガントなソリューション。三角関数の精度が型の精度と等しいことは疑わしいです。定数値を書き込むことを好む人にとって、これは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/にアクセスしてください。
3.14
、3.141592
とatan(1) * 4
?