How to use the PI constant in C++

C++Trigonometry

C++ 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:

  1. on newer platforms (at least on my 64 bit Ubuntu 14.04) I do not need to define the _USE_MATH_DEFINES

  2. 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

as per: https://stackoverflow.com/questions/23524661/how-can-i-calculate-pi-using-bash-command/29988808#29988808

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 inline constexpr T pi_v = unspecified; > inline constexpr double pi = pi_v;

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEtanView Question on Stackoverflow
Solution 1 - C++Ferenc DeakView Answer on Stackoverflow
Solution 2 - C++KonamimanView Answer on Stackoverflow
Solution 3 - C++BuschnicKView Answer on Stackoverflow
Solution 4 - C++Ciro Santilli Путлер Капут 六四事View Answer on Stackoverflow
Solution 5 - C++HenrikView Answer on Stackoverflow
Solution 6 - C++Matthieu M.View Answer on Stackoverflow
Solution 7 - C++AlexView Answer on Stackoverflow
Solution 8 - C++sellibitzeView Answer on Stackoverflow
Solution 9 - C++JoakimView Answer on Stackoverflow
Solution 10 - C++RichieHindleView Answer on Stackoverflow
Solution 11 - C++0xbadf00dView Answer on Stackoverflow
Solution 12 - C++Shital ShahView Answer on Stackoverflow
Solution 13 - C++Sumudu FernandoView Answer on Stackoverflow
Solution 14 - C++Beta JesterView Answer on Stackoverflow
Solution 15 - C++John McFarlaneView Answer on Stackoverflow
Solution 16 - C++Jon GuitonView Answer on Stackoverflow
Solution 17 - C++Jeroen LammertinkView Answer on Stackoverflow
Solution 18 - C++Papa SmurfView Answer on Stackoverflow
Solution 19 - C++Willy GoatView Answer on Stackoverflow
Solution 20 - C++Fazlı KUZUView Answer on Stackoverflow
Solution 21 - C++gjerichView Answer on Stackoverflow
Solution 22 - C++Donald DuckView Answer on Stackoverflow
Solution 23 - C++stackoverflowuser2010View Answer on Stackoverflow
Solution 24 - C++Carl KnoxView Answer on Stackoverflow
Solution 25 - C++SimonView Answer on Stackoverflow