How to use the PI constant in C++
Solution 1
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
Pi can be calculated as atan(1)*4
. You could calculate the value this way and cache it.
Solution 3
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
Solution 4
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 5
Get it from the FPU unit on chip instead:
double get_PI()
{
double pi;
__asm
{
fldpi
fstp pi
}
return pi;
}
double PI = get_PI();
Comments
-
Etan almost 2 years
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?
-
Etan over 14 years
#define _USE_MATH_DEFINES
followed by#include <math.h>
definesM_PI
in visual c++. Thanks. -
Steve Jessop over 14 yearsGood tip. If "you" are a compilation unit then of course you can ensure the macro is defined before anything is included. But if "you" are a header file, it's out of your control.
-
Matthieu M. over 14 yearsIn fact even if "you" are a compilation unit... depending on the ordering of the headers is a the shortest path toward maintenance nightmare...
-
Steve Jessop over 14 yearsYou don't have to depend on the ordering of the headers, though. It doesn't matter whether headers include each other, provided that you do the #define before you #include anything at all (at least, assuming that nothing #undefs it). Same applies to NDEBUG.
-
Dan Moulding almost 14 yearsBoost: Boosting the already unnecessary complexity of C++ since 1999!
-
BuschnicK almost 14 yearsCatchy and partly true. On the other hand boost can be phenomenally useful at times...
-
Rob about 13 yearsWorks with cygwin headers as well.
-
kalu almost 13 yearsThis won't work if you want to define a global variable PI. You will get an error shouting that
'pi' is not declared in this scope
. I am new to C++ so if there is a way to get around this I am not aware of it. -
Richard J. Ross III about 12 yearsYou can always include
cmath
instead ofmath.h
. -
matiu over 11 yearsFor c++11 users:
constexpr double pi() { return std::atan(1)*4; }
-
Thomas Eding over 11 years-1: Works only if
atan(1)*4 == 3.141592653589793238462643383279502884
(roughly speaking). I wouldn't bet on it. Be normal and use a raw literal to define the constant. Why lose precision when you don't need to? -
Ben over 11 years@ThomasEding - my
math.h
file reads#define M_PI 3.14159265358979323846
(if strict ANSI). -
legends2k almost 11 yearsOne can avoid the multiplication operation with
atan2(0, -1);
. -
Sebastian Mach almost 11 years@DanMoulding: Uhm. Is C the only other language you know? Because all other languages I know, except C, have a standard library which is magnitudes bigger than C++' (e.g. Python, Haskell, C#, PHP, Delphi, Erlang, Java, ......). From personal experience, that elitist
not gonna use libs
-opinion is a pest and probably the number one reason for bad software written in C++. -
Admin almost 11 years@phresnel seriously, boost is the only reason why c++ can be as easily written as php with a massive relative performance increase, not to mention its children: json-spirit & websocket++.
-
Sebastian Mach almost 11 years@Gracchus: Yup. C++ without libraries (or without the new C++11 libraries) is, as much as I like that language and as much as I would like to code everything myself, not very productive.
-
R. Martinho Fernandes over 10 years@matiu
atan
is notconstexpr
. -
nacho4d over 10 yearsThis is a great example why we should not take this approach, we people make mistakes, rounding, copy&pasting, etc. I think using M_PI is the right approach.
-
legends2k over 10 yearsEven after defining
_USE_MATH_DEFINES
if GCC complains that's because__STRICT_ANSI__
is defined (perhaps you passed-pedantic
or-std=c++11
) which disallowsM_PI
to be defined, hence undefine it with-D__STRICT_ANSI__
. When defining it yourself, since it's C++, instead of a macro you shouldconstexpr auto M_PI = 3.14159265358979323846;
. -
legends2k over 10 yearsIf one is doing this in C++11, make the
const
aconstexpr
. -
m24p over 10 years@nacho4d I too prefer M_PI if it's available, but not all systems are POSIX compliant. I think this approach is better than the 4*atan(1) method for the cases where M_PI is not available.
-
Timmmm about 10 yearsI believe he said complexity not size. Presumably referring to a) the 3 nested namespaces, and b) defining pi as a templated function rather than just a normal constant.
-
user541686 almost 10 yearsTry
acos(-1)
instead, no need foratan2
. -
developerbmw almost 10 yearsWhy is there a boost answer to almost every C++ question? Boost should be another language otherwise it pollutes C++
-
pqnet almost 10 years@Pharap almost nothing: the only difference is that using
constexpr
enforces the value to be computed at compile time, while the oldconst
do that at program initialization. -
Eugene Ryabtsev almost 10 yearsIt's often less CPU instructions and/or less latency to load an immediate operand than read an operand from a memory location. Also, only expressions that are known at compile-time could be pre-computed (I mean
double x = pi * 1.5;
and the like). If you ever intend to use PI in crunchy math in tight loops, you better make sure the value is known to the compiler. -
Micah over 9 yearsI usually use acos(-1), as you say, they are compile-time evaluated. When I tested M_PI, acos(-1) and atan(1)*4, I got identical values.
-
jimifiki about 9 years@Pharap on my machine, with my compiler, atan(1)*4 generates pi at compile time. I'm not sure that this behavior is specified by the C++99 standard. Using constexpr is better.
-
Pharap about 9 years@jimifiki I've yet to have someone tell me that their compiler doesn't do this when using
const
but does withconstexpr
. If you can find one that doesn't, then and only then will you have something to refute my claim. -
greggo about 9 years@ThomasEding it really should. Especially acos(-1) should give the closest value to pi, since -1 is a special case for acos. Fun fact: let M_PI = pi-delta, (i.e. delta is the rounding error), then library call sin(M_PI) should return delta, with precision of a double. I.e. sin(M_PI) + M_PI, the two added together exactly using suitable means, should give you pi with 100+ significant bits -- if 'sin' is done properly. I've tried this with glibc and it worked.
-
meneldal about 9 yearsThe very common issue in a project is that if you're compiling with Visual Studio for example you don't know in which order the compiler is going to go through your files so if you use
<cmath>
in different places it becomes a big pain (especially if it is included by another library you are including). It would have been much better if they put that part outside of the header guards but well can't do much about that now. The compiler directive works pretty well indeed. -
Etan almost 9 years:-) probably not that platform independent, but a nice additional exotic solution!
-
HelloGoodbye over 8 years@greggo: What data type are you using that has 100+ significant bits? And does "done properly" mean to calculate the exact value without any numerical error?
-
greggo over 8 years@HelloGoodbye plain doubles. 52 bits in M_PI and 52 in sin(M_PI). If you add those together with full precision you get 100 good bits of pi. 'properly' just means that it should give the best result representable for the exact input value, even though the 'fuzz' in x at x = M_PI, multiplied by the derivative of sin(x) at that point (i.e. -1) gives you a 'fuzz' at the function output which of the same magnitude as sin(x). So, from one point of view the result is all fuzz and need not be that accurate, but a library function should still respect the exact input and give the best result.
-
greggo over 8 years@HelloGoodbye specifically, the way I checked it was to obtain the values in python floats (which are 64-bit doubles), convert them to exact rational values with
val.as_integer_ratio()
, find the exact rational sum, and then print that out in decimal to as many places as needed using integer div and mod etc; then compare to published value of pi. Simpler way: you can just printf both original doubles using "%36.34f" and then add them on paper : 3.1415926535897931159979634685441852 + 0.0000000000000001224646799147353207 -
HelloGoodbye over 8 years@greggo You're right, I realized that the sin function only needs to calculate a value with as high precision as the data type allows. It sounds like an interesting trick in that case.
-
HelloGoodbye over 8 years@greggo But I'm wondering how you would construct a sin function that gives that kind precision? It wouldn't work with ordinary Maclaurin expansion, since you already after the two first terms will have a rounding error that is larger the desired precision if the argument is
M_PI
. But if you have found that the method you suggest works, the sin function you are using obviously does give that good precision, but how does it work? -
greggo over 8 years@HelloGoodbye it's done in the argument reduction. something like this: the sin function would start by reducing modulo pi, and it would use a extended accuracy value of pi for that. E.g. if you find that the input x is close to k * pi+x0, with x0 in +/- pi/2, you subtract k*MPI from it, and then you subtract k * pi0, where pi0 is the tiny difference between MPI and the true pi. So for x=MPI we have k=1, and the first subtraction gives exactly 0, and the second gives the more accurate residue. This also allows keeping accuracy with huge inputs like x= 1e20, where k is a really big number.
-
JAB over 8 years@Timmmm You might want to complain to the C++ standards committee about (b), because the STL uses it too now (see
std::numeric_limits
, among other things). -
Timmmm over 8 years@JAB That is true, but at least it is only one nested namespace (and some of
numeric_limits
are constants rather than functions - I'm not sure why they used both approaches. Fortunately C++14 allows templated variables anyway so you could just dodouble d = std::pi;
or whatever. -
JAB over 8 years@Timmmm Boost seems to favor nested namespaces in general. I've found it useful to just alias the namespaces when you need to (e.g.
namespace bmc = boost::math::constants;
or whatever). I wasn't aware that C++14 allows templated variables, though, that's interesting (though technically previous versions allowed them too, they just had to be members of specializations of template classes, hence why you have to usetypename
to tell your compiler a dependent type is actually a type [though I still can't see why compilers can't determine that for themselves in non-ambiguous cases]). -
Nemo over 8 years"Calculating acos or atan is always more expensive" is not true. Any modern optimizing compiler knows all about standard math functions and can constant-propagate through them. See e.g. goo.gl/BvdJyr
-
0xbadf00d about 8 yearsNote that
arg(log(x)) == π
for all0 < x < 1
. -
0xbadf00d about 8 yearsThis is not an answer, but a comment to fritzone's answer.
-
0xbadf00d about 8 yearsYou could also use boost .... Right, but please don't redefine an already defined constant (in a less flexible way).
-
Willy Goat about 8 yearsC++14, just do
static constexpr auto pi = acos(-1);
or justM_PI
-
0xbadf00d about 8 years
std::acos
is not aconstexpr
. So, your code won't compile. -
Willy Goat about 8 years@0xbadf00d I compiled it with g++
-
Eivind Dahl almost 8 yearsWith Visual Studio Community, I get an error using constexpr.
-
Ben Voigt almost 8 years@0xbadf00d: It is a completely standalone answer that provides the steps needed to get
M_PI
working on a particular platform. That isn't a comment on an answer for some other platform any more that an answer for some other platform is a comment on this one. -
Ben Voigt almost 8 years@WillyGoat: Then g++ is wrong, because
acos
is notconstexpr
in C++14, and is not proposed to becomeconstexpr
even in C++17 -
Shital Shah almost 8 yearsCan the downvoter comment on what is wrong with this answer. This is well researched and tested and being in use in real system. I had definitely like to improve it if something is wrong.
-
Parker Coates over 7 years@Nemo, Counter example: godbolt.org/g/DsAern As has been said elsewhere, it appears only GCC does this currently and that's likely because it has declared the basic math functions as
constexpr
. -
Remy Lebeau over 6 yearsFYI, Borland C++ compilers also define
M_PI
without needing_USE_MATH_DEFINES
-
Abderrahim Kitouni over 6 yearsGood answer but the link is dead. I suggest this one instead.
-
VivienLeger about 6 yearsi love how you though out of the box here ;)
-
tobi_s over 5 yearsThe traditional way is to use
4*atan(1.)
:atan
is easy to implement and multiplying by 4 is an exact operation. Of course, modern compilers fold (aim to fold) all constants with the required precision, and it's perfectly reasonable to useacos(-1)
or evenstd::abs(std::arg(std::complex<double>(-1.,0.)))
which is the inverse of Euler's formula and thus more aesthetically pleasing than it seems (I've addedabs
because I don't remember how the complex plane is cut or if that's defined at all). -
Mariusz Jaskółka over 5 yearsAs of 2018, The answer should definetely be updated to use <cmath> instead of <math.h>
-
Grant Rostig over 5 yearsVery nice. It might be necessary to have an "l" or "L" at the end of that number. I get a narrowing warning from my compiler gcc on linux.
-
Matt about 5 yearsI love this answer. It is particularly useful when targeting older x86 platforms which is a small fad as of late where the optimizing compilers aren't as terribly involved as modern ones. Thanks for this Henrik!
-
user14717 over 4 years@DanMoulding: The point of the boost::math::constants is that they are arbitrary precision constants. They can be used in (say) climate codes where quad precision is often required.
-
Kapten-N over 4 years@jaskmar I can't find an M_PI with <cmath> included. However, the answer should perhaps be updated to say M_1_PI instead, because that's the defined value that I can find with <math.h> included. There' also an M_2_PI, which is basically Tau.
-
wcochran over 4 years@BenVoigt are there any math functions that are
constexpr
? Apparently not: stackoverflow.com/questions/17347935/constexpr-math-functions -
Ben Voigt over 4 years@wcochran: There are plenty of NEW math functions that are
constexpr
, see for example (github.com/kthohr/gcem). But they are not backward-compatible with the C functions of the same name, so they can't take over the old names. -
Isaac Pascual about 4 years@0xbadf00d: It compile but you cant use it in a constexpr context
-
midjji about 4 yearsJust so no one accidentally thinks you are serious (again-_-'). This is a terrible solution. The atan implementation is not defined by the standard meaning its implementation and possibly hw dependent. This means that the numerics can be terrible, meaning you may well be better off using 3.14 in general. Further its quite possibly slow, even for the special cases.
-
midjji about 4 yearsThis is a terrible idea. use a per type overloaded template constexpr, that way you get a compile error to force you to define it if a new type appears. Its also generally a terrible because the trig types are not limited to floating point types. So enjoy the atan(1) mistake... The standard does not guarantee that trigonometric functions compute their actual trigonometric values to the accuracy of the type. They generally do not, and it gets worse with e.g. fastmath and is always especially bad for the special values.
-
Elviss Strazdins about 4 years@Pharap here you go: godbolt.org/z/UsGxf5. gcc is actually the only compiler that generates the constant at compile time. Visual Studio and clang does it at runtime by calling atan.
-
Jean-Claude Arbaut over 3 years@ElvissStrazdins Try icc.
-
Jeff Hammond over 3 yearsI had the obvious question "why not constexpr?" and someone already answered this on stackoverflow.com/questions/32814678/…, which might be useful to somebody.
-
Jeff Hammond over 3 yearsThis is a GCC extension and should not be used (stackoverflow.com/questions/32814678/…).
-
Jack G over 3 yearsThat's way more digits than you need.
3.1415927f
is as accurate as you can store with 32bit floats, and3.141592653589793
is as accurate as you can store with 64bit doubles. -
Victor Eijkhout over 3 years@WillyGoat You're proving my private rule about the use of "just": the
acos
is just as non-constexpr asatan
so your suggestion does not work. -
Anachronist about 3 yearsI don't understand why the long double precision pi has only two more digits of accuracy than the double precision pi. That suggests that it's hardly worth using long double.
-
Ciro Santilli OurBigBook.com about 3 years@Anachronist good observation, I'm not too sure why this is the case, let me know if anyone figures it out, I'm lazy to think now :) Related: stackoverflow.com/questions/15176290/…
-
J. Tully about 3 yearsWhy is the float value so far off? 3.xxxxxx74101257324219 ? It should be 3.14159265f
-
Ciro Santilli OurBigBook.com about 3 years@J.Tully Google sugggests 7 figures is correct for 32-bit float: stackoverflow.com/questions/13542944/… I didn't stop to think myself though.
-
sappjw about 3 years@Kapten-N M_1_PI is
1/pi
, notpi
-
Arnaud about 3 years@Anachronist It could be a sign that on g++10, on your machine (like on mine), the long doubles are implemented as 80-bits extended precision, not quadruple precision.
-
Eric Postpischil over 2 yearsThis is not a good solution since the standard headers will define π with a precision suitable for their C++ implementation. That is, they will use as many digits as needed to give π as accurately as the implementation is capable of. They may also use a hexadecimal format to avoid rounding issues in the conversion from decimal to the internal floating-point format. The standard headers should be preferred, and, if one is going to define π oneself, it would be with more digits.
-
Eric Postpischil over 2 years
3.1415926535897932385
is adouble
constant. Accuracy is lost when converting the numeral todouble
, and converting thatdouble
tolong double
leaves the value unchanged, with the accuracy lost. -
stackoverflowuser2010 over 2 yearsWhat exactly does a "C++ implementation" have to do with the number of digits of pi? Are you referring to the bit width of the registers?
-
stackoverflowuser2010 over 2 yearsThis is literally the only good answer to the question. It doesn't include any esoteric header files, doesn't run any further math of trig operations, and doesn't rely on assembly code. It just uses good old fashioned American high school knowledge of math. Kudos, good sir!
-
stackoverflowuser2010 over 2 years@EricPostpischil: What's the answer, bro?
-
mabraham over 2 yearsIt literally doesn't answer the question, which asked for a solution without defining it manually. It is also a path to frustration to introduce inconsistent definitions of constants within the same program.
-
Max Ostrowski over 2 yearsThis does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-
Konstantin Burlachenko over 2 yearsI have upvote because during writing in C++ for 10+ years I have never seen the definition of pi, seems C++20 fixes the issue. "solution without defining it manually." - is stupid, you can do whatever you want. And I'm not sure it's under the responsibility of C to define any constant from the math of physics.
-
parsley72 about 2 yearsWhat if the value of Pi changes? You'll have to go back and edit it manually.