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?