<p>C does not even have <code>M_PI</code> standardized. C++ only <a href="https://stackoverflow.com/a/57285400">added <code>std::numbers::pi</code> very recently</a>. Yes, the <a href="https://langdev.stackexchange.com/a/2028/38">fact that this took so long does hint at some issues</a>. Both languages have an upper bound to their precision of their floating point types (<code>float</code>, <code>double</code>, <code>long double</code>) which are of fixed size. π is just a number and could be offered in <code>float</code>, <code>double</code> and <code>long double</code> form. So, what are the <em>'issues'</em> with adding π?</p>

<c><c++><math>
What obstacles prevented C and C++ from standardizing π?
CC BY-SA 4.0
2023-07-07T01:21:50.840Z
Insufficient locale support, which couldn't handle if [a government were to redefine pi](https://en.wikipedia.org/wiki/Indiana_Pi_Bill).
R.M.
CC BY-SA 4.0
2023-07-07T01:27:36.310Z
@R.M. That doesn't really make sense to me, pi is and will always be the same number, anywhere in the entire universe.
CPlus
CC BY-SA 4.0
2023-07-07T01:36:08.860Z
(I'm pretty sure it's a joke.)
Karl Knechtel
CC BY-SA 4.0
2023-07-07T14:36:09.630Z
It is indeed a joke (hence comment and not answer). But it's also a winking nod to the dangers of baking into the language assumptions which might be valid for you but not for others. (See the various "Falsehoods programmers believe about ..." articles for potential examples.)
R.M.
CC BY-SA 4.0
2023-07-23T04:34:29.940Z
Could it just be about namespace pollution?  As far as I can tell, `M_*` identifiers aren't reserved, so a conforming program could have defined its own `M_PI`.  (But I guess the standard could still define `_M_PI` instead.)
Nate Eldredge
<p>There is no <em>good</em> way to write the exact value of PI in a C program without changing the compiler to add syntax for hex floating point constants; and writing them to lose no bits on conversion is tricky.</p>
<p>Writing <code>const long double pi = 3.141592653589793238462643;</code> doesn't work on most compilers. The last few bits come out wrong.</p>
<p>However you can always get PI by doing <code>atan(1) * 4</code>, and with no loss of precision if your runtime is any good. So there's just insufficient reason to compel the change to the compiler.</p>
<hr />
<p>In comments on this answer it has been asked why we didn't end up with <code>extern const long double pi;</code>. The primary reason is there are no other such constants. All of the constants are actually macros. The secondary reason is the C standard library is itself meant to be <em>portable</em>, and so it was between Unix systems. The hackery required to make such a declaration of pi work (that is, where just assigning it the decimal value wouldn't work, which is the origin of the problem) would invariably end up being non portable. And no, you can't do <code>const long double pi = atan(1) * 4;</code> in the standard library. The no function calls in global initializers rule isn't arbitrary. There's simply no way to compile that.</p>

CC BY-SA 4.0
2023-08-17T17:36:53.367Z
2023-08-17T23:25:23.077Z
2023-08-17T23:25:23.077Z
Joshua
CC BY-SA 4.0
2023-08-17T18:50:54.437Z
Presumably it could be made to work on (more than) "most compilers" if it were specified in the Standard?
Toby Speight
CC BY-SA 4.0
2023-08-17T18:57:34.393Z
@TobySpeight: Getting an exact binary result from a decimal floating point wasn't a solved problem in 1980, so no. You'd just have a non-implementable standard and a backwards compatibility headache with people who took an accidental dependency on pi being wrong.
Joshua
CC BY-SA 4.0
2023-08-17T19:06:45.437Z
It's the _Standard Library_.  So it can use platform-dependent magic to get an exact binary result (perhaps evaluating `atanl(1) * 4` or equivalent within the compiler, or perhaps using a built-in (binary) constant).  No reason for the implementation to use decimal.
Toby Speight
CC BY-SA 4.0
2023-08-17T19:07:56.560Z
@TobySpeight: Oh. you mean `extern const long double pi`. That's a different question.
Joshua
CC BY-SA 4.0
2023-08-17T19:35:16.700Z
Really?  I thought it was very much this question. Maybe I was mistaken.
Toby Speight
CC BY-SA 4.0
2023-08-18T09:55:31.070Z
You could still have the library `#define PI __builtin_pi` if necessary.
Toby Speight
<p>I can't find anything <a href="https://www.open-std.org/JTC1/SC22/WG14/www/docs/n897.pdf" rel="nofollow noreferrer">in the Rationale</a> that specifically addresses mathematical constants, or the lack thereof, so I can only speculate.</p>
<ul>
<li>Other popular programming languages at the time didn't have a standard π constant.  Pascal didn't.  BASIC didn't.  Even FORTRAN, the original language of scientific computing, <a href="https://stackoverflow.com/questions/2157920/why-define-pi-4atan1-d0">didn't have a standard π constant</a> yet.  A lot of code from the era wrote <code>PI = 4 * atan(1)</code> or equivalent to calculate it.</li>
<li>When C was first standardized in 1989, hardware floating-point wasn't as ubiquitous as it is today.  Floating-point coprocessors (like the Intel 8087 for IBM PCs) were an expensive extra used only by serious number-crunchers.  Compilers at the time provided the option to require a coprocessor, to emulate floating-point instructions in software (slowly), or to just not link the floating-point functions at all (hence GCC separating <code>libm</code> from <code>libc</code> to this day).  The perception was that floating point was something to avoid unless you absolutely <em>needed</em> it, so <code>&lt;math.h&gt;</code> would be kept as minimalist as possible.</li>
<li>The committee didn't want to waste time on arguments about which constants to define (π?  <a href="https://en.wikipedia.org/wiki/E_(mathematical_constant)" rel="nofollow noreferrer">e</a>?  <a href="https://en.wikipedia.org/wiki/Golden_ratio" rel="nofollow noreferrer">φ</a>?  <a href="https://tauday.com/tau-manifesto" rel="nofollow noreferrer">τ</a>?) or what type they should have (<code>float</code>?  <code>double</code>?  <code>long double</code>?  All three?), and it was easier to just do nothing and leave this stuff up to the programmers.</li>
</ul>

CC BY-SA 4.0
2023-07-06T04:27:16.213Z
2023-07-06T18:17:18.197Z
2023-07-06T18:17:18.197Z
dan04
CC BY-SA 4.0
2023-07-06T13:47:50.007Z
I would note that to this day, in the embedded world -- where C still reigns -- there are quite a lot of micro-processors that still don't support floating points.
Matthieu M.
CC BY-SA 4.0
2023-07-06T18:27:12.360Z
@MatthieuM.: I'd assume you couldn't `#include <math.h>` on such machines.  C does define some FP constants like `DBL_MIN`, so C implementations without FP support already need to "deal with" that.  Or not since they're defined as CPP macros, and thus do nothing when not used.
Peter Cordes
CC BY-SA 4.0
2023-07-06T21:20:37.850Z
I would also add a fourth point: π is easy to get at near machine precision if you have working trig functionality and multiplication (`4*atan(1)`), and even without that you can get a reasonably good approximation suitable for many end-user applications with a single division operation (22/7, 333/106, 355/113, etc). IOW, if a programmer truly needed it, they could easily compute it themselves.
Austin Hemmelgarn
CC BY-SA 4.0
2023-10-24T16:01:17.880Z
@AustinHemmelgarn: If `x` is a value which is close to an integer multiple of the value of 2pi the machine's trig functions use for argument reduction, then the mathematical result one would get from subtracting the result of the machine's `sin(x)` function from `x` would be even closer to the value of 2pi the machine uses for argument reduction. however precise that representation happens to be.
supercat
<blockquote>
<p>Both languages have an upper bound to their precision of their floating point types (<code>float</code> <code>double</code> <code>long double</code>) which are of fixed size.</p>
</blockquote>
<p>This does not appear to be true. The floating-point numbers types have lower bounds but not upper bounds for their bit-widths (see <a href="https://en.wikipedia.org/wiki/C_data_types#Main_types" rel="nofollow noreferrer">Wikipedia</a> or <a href="https://stackoverflow.com/q/25524355/12299000">Stack Overflow</a>) and there weren't standardised floating-point types that require exact widths until C++23 (see <a href="https://stackoverflow.com/a/76201716/12299000">Stack Overflow</a>).</p>
<p>So, mandating a specific value for <code>M_PI</code> would preclude implementations from using more precise values in implementations where more precision would be supported.</p>
<p>I suppose the spec could have said something like &quot;there must be a constant <code>M_PI</code> of type <code>double</code> whose value is the closest representable value to the mathematical constant π&quot;. That would work as a specification, though it would be a bit unusual to specify a constant without giving it a literal value. It would also potentially preclude implementations like <a href="https://stackoverflow.com/a/30647428/12299000">this one</a>, which load whatever value of π the processor uses; the processor's value of π might load into a register with more bits of precision than a <code>double</code> would normally have.</p>

CC BY-SA 4.0
2023-07-06T13:18:25.073Z
2023-10-23T16:46:33.213Z
2023-10-23T16:46:33.213Z
kaya3
CC BY-SA 4.0
2023-07-06T19:43:02.987Z
x87 is a known target.  `fldpi` loads an 80-bit constant that's the nearest representable `long double` to Pi, and `fst qword` or `dword` will round that to the nearest representable `double` or `float`.  AFAIK, all CPUs supporting x87 floating point use the same constant for `fldpi`.  If that wasn't the case, and the same machine-code ABI could result in constants or calculations with different precision on different machines, then yeah, *that* would be incompatible with a specific constant or with there being a definition for `std::numeric_limits<long double>::digits` and so on
Peter Cordes
CC BY-SA 4.0
2023-07-06T19:46:22.747Z
(With x87 being able to set its precision (mantissa rounding), and some implementations actually doing that to speed up div and sqrt, there might be a *potential* problem, at least if you linked Direct3D in a 32-bit Windows executable which 
 makes `double` as imprecise as `float`! 
 (https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/).  But I'd consider that to be like an aggressive `-ffast-math` type of thing, breaking IEEE guarantees.  Normally Linux leaves precision at full, and MSVC on Windows left precision = 53-bit mantissa (enough for `double`)
Peter Cordes
CC BY-SA 4.0
2023-07-06T21:50:58.993Z
Personally I see nothing wrong as mandating `M_PI` as containing *the closest representable value to the ratio of a circle's circumference to its diameter*.
CPlus
CC BY-SA 4.0
2023-07-06T21:51:56.593Z
Why would an implementation have to load pi?
CPlus
CC BY-SA 4.0
2023-07-06T22:14:09.330Z
Better than having a constant for  π would be to have standard functions which compute sin(2πx), cos(2πx), tan(2πx), atn(x,y)/2π, etc.  Such functions could in many cases not only be faster than combination of a multiplication and a trig function, but they could in many cases be faster than a trig function without the 2π factor since the cost of argument reduction would be greatly reduced.
supercat
CC BY-SA 4.0
2023-10-21T20:59:54.713Z
@supercat C23 adds functions to compute `sin(pi*x)` etc called `sinpi()`, `cospi()`, etc. So that is a step in the right direction.
CPlus
CC BY-SA 4.0
2023-10-23T16:27:20.217Z
@user16217248: I wonder how long it will be before such functions are routinely implemented without a "scale by pi" step?  I also wonder if there might be value in a family of "rough" trig functions which would indicate that results related to any angle within e.g. π/65536 of the correct angle would be equally acceptable, minimizing the number of cleanup steps after using e.g. an "approximate sine" function.
supercat
CC BY-SA 4.0
2023-10-23T16:41:06.493Z
@supercat If you only need results accurate to within an input angle of pi/65536, then it probably makes more sense to just precompute an array of results; it takes kilobytes of memory and is fast to query. In that case it makes sense not to include it in the standard library because building such a lookup table is trivial for the user to do themselves, and they can tune it to the precision they want for their own application.
kaya3
CC BY-SA 4.0
2023-10-23T16:45:01.890Z
Re: x87 using an 80-bit constant, that's actually a decent argument in favour of *not* specifying "the closest representable `double` value", because `double`s generally are 64 bits, not 80. If it had to be the closest 64-bit approximation, then using a more accurate 80-bit value where possible would violate the spec.
kaya3
CC BY-SA 4.0
2023-10-23T16:53:58.733Z
@kaya3 They could define a PI constant for `double` `float` and `long double` or alternatively just for `long double` as the closest representable value of the corresponding type to the actual constant. Technically only `long double` constants would be required because narrowing conversions from `long double` to `double` or `float` can be done at compile time.
CPlus
CC BY-SA 4.0
2023-10-23T16:54:36.130Z
@kaya3: There are a variety of means an implementation could use to achieve that level of precision.  Using a four-quadrant table may be faster or slower than using a one-quadrant table with some additional logic, and performing a lookup in a 65536-entry table may be faster or slower than performing two lookups in a 256-entry table along with a multiply and add.  If a program is expected to run on different platforms where different approaches may be better, a standard library function could adapt more readily than user code.
supercat
CC BY-SA 4.0
2023-10-23T17:04:18.240Z
@supercat A one-quadrant table wouldn't be 256 entries, it would be 32768. But there are also many situations where there is no range/symmetry reduction needed because in the application logic the input angle is already known to be within the first quadrant. One standard library function can't take advantage of such cases, you would need several.
kaya3
CC BY-SA 4.0
2023-10-24T15:56:27.347Z
Instead of saying "closest representable value", they could specify it in terms of the implementation's trig functions, e.g. `M_PI == acos(-1)`.
Barmar
<p>There is no deep reason. The answer is social:</p>
<ul>
<li><p>The C standard does not specify any constant for π. We can only speculate on why, but ultimately, the set of things the C standard does and does not specify is somewhat arbitrary. We have no reason to believe this was an intentional omission rather than something nobody has bothered to specify.</p>
</li>
<li><p>POSIX <a href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/math.h.html" rel="noreferrer">specifies that <code>math.h</code> must define <code>M_PI</code></a>, but only if the appropriate feature test macro is set. <a href="https://learn.microsoft.com/en-us/cpp/c-runtime-library/math-constants" rel="noreferrer">MSVC requires <code>_USE_MATH_DEFINES</code> be defined</a> before <code>math.h</code> is included. These were often used by C++ programmers, albeit non-portably.</p>
</li>
<li><p>A π constant is not difficult for programmers to define, so the absence of a portable way to access it was not a showstopper. Some programmers defined it themselves, others used definitions provided from third-party libraries like Boost.</p>
</li>
<li><p>Eventually, someone decided that relying on the non-portable definition of <code>M_PI</code> or user definitions was sufficiently annoying that they <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r8.pdf" rel="noreferrer">took the time to write up a proposal to standardize math constants</a> in the C++ standard library, and that was that.</p>
</li>
</ul>
<p>Nowhere in the proposal is there any indication that there were any technical obstacles to its implementation. Indeed, it makes it sound quite as though it was an arbitrary omission that nobody had bothered to rectify:</p>
<blockquote>
<p>C++ inherited from C a rich library of mathematical functions which continues to grow with every release. Amid all this abundance, there is a strange gap: none of the major mathematical constants is defined in the standard. This proposal is aimed to rectify this omission.</p>
</blockquote>
<p>Standardizing anything in a language with as many users as C++ is slow and takes a lot of time, even if it’s fairly uncontroversial. Sometimes obvious inconveniences don’t get fixed because nobody cares enough to go through that process when easy workarounds are available. Perhaps they hope someone else will get around to it.</p>
<p>Eventually, someone did.</p>

CC BY-SA 4.0
2023-07-06T01:13:40.037Z
2023-07-06T01:13:40.037Z
Alexis King
CC BY-SA 4.0
2023-07-06T12:43:34.033Z
Well, there certainly are technical obstacles to representing irrational numbers in ways that are both exact and generally useful. They're not necessarily relevant, as any DIY approach will have similar problems.
user126527
# What obstacles prevented C and C++ from standardizing π?
Posted by: username_0 on 2023-07-06
C does not even have `M_PI` standardized. C++ only [added `std::numbers::pi` very recently](https://stackoverflow.com/a/57285400). Yes, the [fact that this took so long does hint at some issues](https://langdev.stackexchange.com/a/2028/38). Both languages have an upper bound to their precision of their floating point types (`float`, `double`, `long double`) which are of fixed size. π is just a number and could be offered in `float`, `double` and `long double` form. So, what are the *'issues'* with adding π?
**Tags:** c c++ math
> **Comments:**
> **username_1**: Insufficient locale support, which couldn't handle if [a government were to redefine pi](https://en.wikipedia.org/wiki/Indiana_Pi_Bill).  
> **username_0**: @R.M. That doesn't really make sense to me, pi is and will always be the same number, anywhere in the entire universe.  
> **username_2**: (I'm pretty sure it's a joke.)  
> **username_1**: It is indeed a joke (hence comment and not answer). But it's also a winking nod to the dangers of baking into the language assumptions which might be valid for you but not for others. (See the various "Falsehoods programmers believe about ..." articles for potential examples.)  
> **username_3**: Could it just be about namespace pollution?  As far as I can tell, `M_*` identifiers aren't reserved, so a conforming program could have defined its own `M_PI`.  (But I guess the standard could still define `_M_PI` instead.)  
---
## 4 answers
### Answer by username_11 on 2023-07-06. Score: 10 | Accepted answer
> Both languages have an upper bound to their precision of their floating point types (`float` `double` `long double`) which are of fixed size.

This does not appear to be true. The floating-point numbers types have lower bounds but not upper bounds for their bit-widths (see [Wikipedia](https://en.wikipedia.org/wiki/C_data_types#Main_types) or [Stack Overflow](https://stackoverflow.com/q/25524355/12299000)) and there weren't standardised floating-point types that require exact widths until C++23 (see [Stack Overflow](https://stackoverflow.com/a/76201716/12299000)).

So, mandating a specific value for `M_PI` would preclude implementations from using more precise values in implementations where more precision would be supported.

I suppose the spec could have said something like "there must be a constant `M_PI` of type `double` whose value is the closest representable value to the mathematical constant π". That would work as a specification, though it would be a bit unusual to specify a constant without giving it a literal value. It would also potentially preclude implementations like [this one](https://stackoverflow.com/a/30647428/12299000), which load whatever value of π the processor uses; the processor's value of π might load into a register with more bits of precision than a `double` would normally have.
> **Comments:**
> **username_8** (2023-07-06): x87 is a known target.  `fldpi` loads an 80-bit constant that's the nearest representable `long double` to Pi, and `fst qword` or `dword` will round that to the nearest representable `double` or `float`.  AFAIK, all CPUs supporting x87 floating point use the same constant for `fldpi`.  If that wasn't the case, and the same machine-code ABI could result in constants or calculations with different precision on different machines, then yeah, *that* would be incompatible with a specific constant or with there being a definition for `std::numeric_limits<long double>::digits` and so on  
> **username_8** (2023-07-06): (With x87 being able to set its precision (mantissa rounding), and some implementations actually doing that to speed up div and sqrt, there might be a *potential* problem, at least if you linked Direct3D in a 32-bit Windows executable which 
 makes `double` as imprecise as `float`! 
 (https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/).  But I'd consider that to be like an aggressive `-ffast-math` type of thing, breaking IEEE guarantees.  Normally Linux leaves precision at full, and MSVC on Windows left precision = 53-bit mantissa (enough for `double`)  
> **username_0** (2023-07-06): Personally I see nothing wrong as mandating `M_PI` as containing *the closest representable value to the ratio of a circle's circumference to its diameter*.  
> **username_0** (2023-07-06): Why would an implementation have to load pi?  
> **username_10** (2023-07-06): Better than having a constant for  π would be to have standard functions which compute sin(2πx), cos(2πx), tan(2πx), atn(x,y)/2π, etc.  Such functions could in many cases not only be faster than combination of a multiplication and a trig function, but they could in many cases be faster than a trig function without the 2π factor since the cost of argument reduction would be greatly reduced.  
> **username_0** (2023-10-21): @supercat C23 adds functions to compute `sin(pi*x)` etc called `sinpi()`, `cospi()`, etc. So that is a step in the right direction.  
> **username_10** (2023-10-23): @user16217248: I wonder how long it will be before such functions are routinely implemented without a "scale by pi" step?  I also wonder if there might be value in a family of "rough" trig functions which would indicate that results related to any angle within e.g. π/65536 of the correct angle would be equally acceptable, minimizing the number of cleanup steps after using e.g. an "approximate sine" function.  
> **username_11** (2023-10-23): @supercat If you only need results accurate to within an input angle of pi/65536, then it probably makes more sense to just precompute an array of results; it takes kilobytes of memory and is fast to query. In that case it makes sense not to include it in the standard library because building such a lookup table is trivial for the user to do themselves, and they can tune it to the precision they want for their own application.  
> **username_11** (2023-10-23): Re: x87 using an 80-bit constant, that's actually a decent argument in favour of *not* specifying "the closest representable `double` value", because `double`s generally are 64 bits, not 80. If it had to be the closest 64-bit approximation, then using a more accurate 80-bit value where possible would violate the spec.  
> **username_0** (2023-10-23): @kaya3 They could define a PI constant for `double` `float` and `long double` or alternatively just for `long double` as the closest representable value of the corresponding type to the actual constant. Technically only `long double` constants would be required because narrowing conversions from `long double` to `double` or `float` can be done at compile time.  
> **username_10** (2023-10-23): @kaya3: There are a variety of means an implementation could use to achieve that level of precision.  Using a four-quadrant table may be faster or slower than using a one-quadrant table with some additional logic, and performing a lookup in a 65536-entry table may be faster or slower than performing two lookups in a 256-entry table along with a multiply and add.  If a program is expected to run on different platforms where different approaches may be better, a standard library function could adapt more readily than user code.  
> **username_11** (2023-10-23): @supercat A one-quadrant table wouldn't be 256 entries, it would be 32768. But there are also many situations where there is no range/symmetry reduction needed because in the application logic the input angle is already known to be within the first quadrant. One standard library function can't take advantage of such cases, you would need several.  
> **username_12** (2023-10-24): Instead of saying "closest representable value", they could specify it in terms of the implementation's trig functions, e.g. `M_PI == acos(-1)`.  
---
### Answer by username_13 on 2023-07-06. Score: 25
There is no deep reason. The answer is social:

* The C standard does not specify any constant for π. We can only speculate on why, but ultimately, the set of things the C standard does and does not specify is somewhat arbitrary. We have no reason to believe this was an intentional omission rather than something nobody has bothered to specify.
* POSIX [specifies that `math.h` must define `M_PI`](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/math.h.html), but only if the appropriate feature test macro is set. [MSVC requires `_USE_MATH_DEFINES` be defined](https://learn.microsoft.com/en-us/cpp/c-runtime-library/math-constants) before `math.h` is included. These were often used by C++ programmers, albeit non-portably.
* A π constant is not difficult for programmers to define, so the absence of a portable way to access it was not a showstopper. Some programmers defined it themselves, others used definitions provided from third-party libraries like Boost.
* Eventually, someone decided that relying on the non-portable definition of `M_PI` or user definitions was sufficiently annoying that they [took the time to write up a proposal to standardize math constants](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r8.pdf) in the C++ standard library, and that was that.

Nowhere in the proposal is there any indication that there were any technical obstacles to its implementation. Indeed, it makes it sound quite as though it was an arbitrary omission that nobody had bothered to rectify:

> C++ inherited from C a rich library of mathematical functions which continues to grow with every release. Amid all this abundance, there is a strange gap: none of the major mathematical constants is defined in the standard. This proposal is aimed to rectify this omission.

Standardizing anything in a language with as many users as C++ is slow and takes a lot of time, even if it’s fairly uncontroversial. Sometimes obvious inconveniences don’t get fixed because nobody cares enough to go through that process when easy workarounds are available. Perhaps they hope someone else will get around to it.

Eventually, someone did.
> **Comments:**
> **username_14** (2023-07-06): Well, there certainly are technical obstacles to representing irrational numbers in ways that are both exact and generally useful. They're not necessarily relevant, as any DIY approach will have similar problems.  
---
### Answer by username_6 on 2023-07-06. Score: 8
I can't find anything [in the Rationale](https://www.open-std.org/JTC1/SC22/WG14/www/docs/n897.pdf) that specifically addresses mathematical constants, or the lack thereof, so I can only speculate.

* Other popular programming languages at the time didn't have a standard π constant. Pascal didn't. BASIC didn't. Even FORTRAN, the original language of scientific computing, [didn't have a standard π constant](https://stackoverflow.com/questions/2157920/why-define-pi-4atan1-d0) yet. A lot of code from the era wrote `PI = 4 * atan(1)` or equivalent to calculate it.
* When C was first standardized in 1989, hardware floating-point wasn't as ubiquitous as it is today. Floating-point coprocessors (like the Intel 8087 for IBM PCs) were an expensive extra used only by serious number-crunchers. Compilers at the time provided the option to require a coprocessor, to emulate floating-point instructions in software (slowly), or to just not link the floating-point functions at all (hence GCC separating `libm` from `libc` to this day). The perception was that floating point was something to avoid unless you absolutely *needed* it, so  would be kept as minimalist as possible.
* The committee didn't want to waste time on arguments about which constants to define (π? [e](https://en.wikipedia.org/wiki/E_(mathematical_constant))? [φ](https://en.wikipedia.org/wiki/Golden_ratio)? [τ](https://tauday.com/tau-manifesto)?) or what type they should have (`float`? `double`? `long double`? All three?), and it was easier to just do nothing and leave this stuff up to the programmers.
> **Comments:**
> **username_7** (2023-07-06): I would note that to this day, in the embedded world -- where C still reigns -- there are quite a lot of micro-processors that still don't support floating points.  
> **username_8** (2023-07-06): @MatthieuM.: I'd assume you couldn't `#include <math.h>` on such machines.  C does define some FP constants like `DBL_MIN`, so C implementations without FP support already need to "deal with" that.  Or not since they're defined as CPP macros, and thus do nothing when not used.  
> **username_9** (2023-07-06): I would also add a fourth point: π is easy to get at near machine precision if you have working trig functionality and multiplication (`4*atan(1)`), and even without that you can get a reasonably good approximation suitable for many end-user applications with a single division operation (22/7, 333/106, 355/113, etc). IOW, if a programmer truly needed it, they could easily compute it themselves.  
> **username_10** (2023-10-24): @AustinHemmelgarn: If `x` is a value which is close to an integer multiple of the value of 2pi the machine's trig functions use for argument reduction, then the mathematical result one would get from subtracting the result of the machine's `sin(x)` function from `x` would be even closer to the value of 2pi the machine uses for argument reduction. however precise that representation happens to be.  
---
### Answer by username_4 on 2023-08-17. Score: 4
There is no *good* way to write the exact value of PI in a C program without changing the compiler to add syntax for hex floating point constants; and writing them to lose no bits on conversion is tricky.

Writing `const long double pi = 3.141592653589793238462643;` doesn't work on most compilers. The last few bits come out wrong.

However you can always get PI by doing `atan(1) * 4`, and with no loss of precision if your runtime is any good. So there's just insufficient reason to compel the change to the compiler.

---

In comments on this answer it has been asked why we didn't end up with `extern const long double pi;`. The primary reason is there are no other such constants. All of the constants are actually macros. The secondary reason is the C standard library is itself meant to be *portable*, and so it was between Unix systems. The hackery required to make such a declaration of pi work (that is, where just assigning it the decimal value wouldn't work, which is the origin of the problem) would invariably end up being non portable. And no, you can't do `const long double pi = atan(1) * 4;` in the standard library. The no function calls in global initializers rule isn't arbitrary. There's simply no way to compile that.
> **Comments:**
> **username_5** (2023-08-17): Presumably it could be made to work on (more than) "most compilers" if it were specified in the Standard?  
> **username_4** (2023-08-17): @TobySpeight: Getting an exact binary result from a decimal floating point wasn't a solved problem in 1980, so no. You'd just have a non-implementable standard and a backwards compatibility headache with people who took an accidental dependency on pi being wrong.  
> **username_5** (2023-08-17): It's the _Standard Library_.  So it can use platform-dependent magic to get an exact binary result (perhaps evaluating `atanl(1) * 4` or equivalent within the compiler, or perhaps using a built-in (binary) constant).  No reason for the implementation to use decimal.  
> **username_4** (2023-08-17): @TobySpeight: Oh. you mean `extern const long double pi`. That's a different question.  
> **username_5** (2023-08-17): Really?  I thought it was very much this question. Maybe I was mistaken.  
> **username_5** (2023-08-18): You could still have the library `#define PI __builtin_pi` if necessary.  
---
