C++20 std::numbers::pi
At last, it has arrived: http://eel.is/c++draft/numbers
main.cpp
#include <cfloat>
#include <cstdio>
#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;
printf("\nhex \n");
printf("float %A\n", std::numbers::pi_v<float>);
printf("double %A\n", std::numbers::pi);
// Doesn't print the result in a very comparable way because %LA
// randomly has a different hex grouping than %A.
// 0XC.90FDAA22168C235P-2
printf("long double %LA\n", std::numbers::pi_v<long double> - (long double)std::numbers::pi);
printf("exact %s\n", "0x1.921FB54442D18469898CC51701B839A252049C1114CF98E803");
printf("\nLDBL_MANT_DIG=%d\n", LDBL_MANT_DIG);
}
Compile and run:
g++ -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
hex
float 0X1.921FB6P+1
double 0X1.921FB54442D18P+1
long double 0X8.D4P-56
exact 0x1.921FB54442D18469898CC51701B839A252049C1114CF98E803
LDBL_MANT_DIG=64
It is a bit easier to make sense of the precision of the hex output, remembering that in IEEE 754:
- 23 bit significand
- 52 bit significand
- 112 bit significand
Tested on Ubuntu 20.04 amd64, GCC 10.2.0
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 and the hex one was obtained with:
echo "scale=60; obase=16; 4*a(1)/2" | BC_LINE_LENGTH=0 bc -l
The division by 2 is to align bc hex output to C hex output bits so we can compare them nicely.
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
3.14,3.141592andatan(1) * 4?