How to use the PI constant in C++

Viewed 1438825

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?

25 Answers

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: How can I calculate pi using Bash command

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

There is also a std::numbers::e of course :-) How to calculate Euler constant or Euler powered in C++?

These constants use the C++14 variable template feature: C++14 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

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>

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.

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

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;
}

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.

#include <cmath>
const long double pi = acos(-1.L);

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

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.

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.

Related