How to use the PI constant in C++
C++TrigonometryC++ Problem Overview
I want to use the PI constant and trigonometric functions in some C++ program. I get the trigonometric functions with include <math.h>
. However, there doesn't seem to be a definition for PI in this header file.
How can I get PI without defining it manually?
C++ Solutions
Solution 1 - C++
On some (especially older) platforms (see the comments below) you might need to
#define _USE_MATH_DEFINES
and then include the necessary header file:
#include <math.h>
and the value of pi can be accessed via:
M_PI
In my math.h
(2014) it is defined as:
# define M_PI 3.14159265358979323846 /* pi */
but check your math.h
for more. An extract from the "old" math.h
(in 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.
*/
However:
-
on newer platforms (at least on my 64 bit Ubuntu 14.04) I do not need to define the
_USE_MATH_DEFINES
-
On (recent) Linux platforms there are
long double
values too provided as a GNU Extension:define M_PIl 3.141592653589793238462643383279502884L /* pi */
Solution 2 - C++
Pi can be calculated as atan(1)*4
. You could calculate the value this way and cache it.
Solution 3 - C++
You could also use boost, which defines important math constants with maximum accuracy for the requested type (i.e. float vs double).
const double pi = boost::math::constants::pi<double>();
Check out the boost documentation for more examples.
Solution 4 - C++
C++20 std::numbers::pi
At last, it has arrived: http://eel.is/c++draft/numbers
main.cpp
#include <numbers> // std::numbers
#include <iomanip>
#include <iostream>
int main() {
std::cout << std::fixed << std::setprecision(20);
std::cout << "float " << std::numbers::pi_v<float> << std::endl;
std::cout << "double " << std::numbers::pi << std::endl;
std::cout << "long double " << std::numbers::pi_v<long double> << std::endl;
std::cout << "exact " << "3.141592653589793238462643383279502884197169399375105820974944" << std::endl;
}
where the exact result was calculated with:
echo "scale=60; 4*a(1)" | BC_LINE_LENGTH=0 bc -l
Compile and run:
g++-10 -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Output:
float 3.14159274101257324219
double 3.14159265358979311600
long double 3.14159265358979323851
exact 3.141592653589793238462643383279502884197169399375105820974944
Tested on Ubuntu 20.04 amd64, GCC 10.2.0
The accepted proposal describes:
> 5.0. “Headers” [headers]
In the table [tab:cpp.library.headers], a new <math>
header needs to be added.
>
> [...]
>
> namespace std {
> namespace math {
> template
There is also a std::numbers::e
of course :-) https://stackoverflow.com/questions/18773343/how-to-calculate-euler-constant-or-euler-powered-in-c/57285506#57285506
These constants use the C++14 variable template feature: https://stackoverflow.com/questions/21051141/c14-variable-templates-what-is-their-purpose-any-usage-example
In earlier versions of the draft, the constant was under std::math::pi
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf
Solution 5 - C++
Get it from the FPU unit on chip instead:
double get_PI()
{
double pi;
__asm
{
fldpi
fstp pi
}
return pi;
}
double PI = get_PI();
Solution 6 - C++
Rather than writing
#define _USE_MATH_DEFINES
I would recommend using -D_USE_MATH_DEFINES
or /D_USE_MATH_DEFINES
depending on your compiler.
This way you are assured that even in the event of someone including the header before you do (and without the #define) you will still have the constants instead of an obscure compiler error that you will take ages to track down.
Solution 7 - C++
I would recommend just typing in pi to the precision you need. This would add no calculation time to your execution, and it would be portable without using any headers or #defines. Calculating acos or atan is always more expensive than using a precalculated value.
const double PI =3.141592653589793238463;
const float PI_F=3.14159265358979f;
Solution 8 - C++
Since the official standard library doesn't define a constant PI you would have to define it yourself. So the answer to your question "How can I get PI without defining it manually?" is "You don't -- or you rely on some compiler-specific extensions.". If you're not concerned about portability you could check your compiler's manual for this.
C++ allows you to write
const double PI = std::atan(1.0)*4;
but the initialization of this constant is not guaranteed to be static. The G++ compiler however handles those math functions as intrinsics and is able to compute this constant expression at compile-time.
Solution 9 - C++
From the Posix man page of math.h:
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
Solution 10 - C++
Standard C++ doesn't have a constant for PI.
Many C++ compilers define M_PI
in cmath
(or in math.h
for C) as a non-standard extension. You may have to #define _USE_MATH_DEFINES
before you can see it.
Solution 11 - C++
I would do
template<typename T>
T const pi = std::acos(-T(1));
or
template<typename T>
T const pi = std::arg(-std::log(T(2)));
I would not typing in π to the precision you need. What is that even supposed to mean? The precision you need is the precision of T
, but we know nothing about T
.
You might say: What are you talking about? T
will be float
, double
or long double
. So, just type in the precision of long double
, i.e.
template<typename T>
T const pi = static_cast<T>(/* long double precision π */);
But do you really know that there won't be a new floating point type in the standard in the future with an even higher precision than long double
? You don't.
And that's why the first solution is beautiful. You can be quite sure that the standard would overload the trigonometric functions for a new type.
And please, don't say that the evaluation of a trigonometric function at initialization is a performance penalty.
Solution 12 - C++
I use following in one of my common header in the project that covers all bases:
#define _USE_MATH_DEFINES
#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
#ifndef M_PIl
#define M_PIl (3.14159265358979323846264338327950288)
#endif
On a side note, all of below compilers define M_PI and M_PIl constants if you include <cmath>
. There is no need to add `#define _USE_MATH_DEFINES which is only required for VC++.
x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+
Solution 13 - C++
I generally prefer defining my own: const double PI = 2*acos(0.0);
because not all implementations provide it for you.
The question of whether this function gets called at runtime or is static'ed out at compile time is usually not an issue, because it only happens once anyway.
Solution 14 - C++
I just came across this article by Danny Kalev which has a great tip for C++14 and up.
template<typename T>
constexpr T pi = T(3.1415926535897932385);
I thought this was pretty cool (though I would use the highest precision PI in there I could), especially because templates can use it based on type.
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>
Solution 15 - C++
In the C++20 standard library, π is defined as std::numbers::pi_v
for float
, double
and long double
, e.g.
#include <numbers>
auto n = std::numbers::pi_v<float>;
and may be specialized for user-defined types.
Solution 16 - C++
Some elegant solutions. I am doubtful that the precision of the trigonometric functions is equal to the precision of the types though. For those that prefer to write a constant value, this works for g++ :-
template<class T>
class X {
public:
static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}
256 decimal digit accuracy should be enough for any future long long long double type. If more are required visit https://www.piday.org/million/.
Solution 17 - C++
Values like M_PI, M_PI_2, M_PI_4, etc are not standard C++ so a constexpr seems a better solution. Different const expressions can be formulated that calculate the same pi and it concerns me whether they (all) provide me the full accuracy. The C++ standard does not explicitly mention how to calculate pi. Therefore, I tend to fall back to defining pi manually. I would like to share the solution below which supports all kind of fractions of pi in full accuracy.
#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;
}
Solution 18 - C++
On windows (cygwin + g++), I've found it necessary to add the flag -D_XOPEN_SOURCE=500
for the preprocessor to process the definition of M_PI
in math.h
.
Solution 19 - C++
C++14 lets you do static constexpr auto pi = acos(-1);
Solution 20 - C++
You can use that:
#define _USE_MATH_DEFINES // for C++
#include <cmath>
#define _USE_MATH_DEFINES // for C
#include <math.h>
Math Constants are not defined in Standard C/C++. To use them, you must first define _USE_MATH_DEFINES
and then include cmath
or math.h
.
Solution 21 - C++
#include <cmath>
const long double pi = acos(-1.L);
Solution 22 - C++
You can do this:
#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
If M_PI
is already defined in cmath
, this won't do anything else than include cmath
. If M_PI
isn't defined (which is the case for example in Visual Studio), it will define it. In both cases, you can use M_PI
to get the value of pi.
This value of pi comes from Qt Creator's qmath.h.
Solution 23 - C++
I've memorized pi to 11 digits since college (maybe high school), so this is always my preferred approach:
#ifndef PI
#define PI 3.14159265359
#endif
Solution 24 - C++
15 decimal places got man to the lunar surface and back. Anything beyond this is astronomical in scale. Would you be able to measure this, practically, on a smaller scale? Others have spent months calculating to trillions of digits. This isn't useful beyond getting into the record books.
Know that you can calculate pi to an arbitrary length, but keep is practical.
Solution 25 - C++
I don't like #defines since they are simple textual substitutions with zero type safety. They can also cause problems using expressions if brackets are omitted e.g.
#define T_PI 2*PI
should really be
#define T_PI (2*PI)
My current solution to this problem is to use hard-coded values for constants, e.g. in my_constants.hxx
namespace Constants {
constexpr double PI = 3.141... ;
}
However I do not hard-code the values (since I don't like that approach either), instead I use a separate Fortran program to write this file. I use Fortran because it fully supports quad precision (C++ on VisualStudio doesn't) and trig functions are the C++ equivalent of constexpr. E.g.
real(8), parameter :: pi = 4*atan(1.0d0)
No doubt other languages can be used to do the same thing.