Best platform independent pi constant?
The function below calculates pi without relying on any libraries at all.
Also, the type of its result is a template parameter.
Platform ueber-independence is stifled a bit because it only works with fixed-precision fractional types -- the calculated value needs to converge and remain constant over 2 iterations.
So if you specify some kind of arbitrary-precision rational or floating-point class which will automatically increase its precision as needed, a call to this function will not end well.
#include <iostream>
#include <iomanip>
namespace golf {
template <typename T> inline T calc_pi() {
T sum=T(0), k8=T(0), fac=T(1);
for(;;) {
const T next =
sum + fac*(T(4)/(k8+T(1))-T(2)/(k8+T(4))-T(1)/(k8+T(5))-T(1)/(k8+T(6)));
if(sum == next) return sum;
sum=next;
fac /= T(16);
k8 += T(8);
} }
static const auto PI = calc_pi<double>();
}
int main() {
std::cout << std::setprecision(16) << golf::PI << std::endl;
return 0;
}
Meeting C++ has an article on the different options for generating pi: C++ & π they discuss some of the options, from cmath, which is not platform independent:
double pi = M_PI;
std::cout << pi << std::endl;
and from boost:
std::cout << boost::math::constants::pi<double>() << std::endl
and using atan, with constexpr removed since as SchighSchagh points out that is not platform independent:
double const_pi() { return std::atan(1)*4; }
I gathered all the methods into a live example:
#include <iostream>
#include <cmath>
#include <boost/math/constants/constants.hpp>
double piFunc() { return std::atan(1)*4; }
int main()
{
double pi = M_PI;
std::cout << pi << std::endl;
std::cout << boost::math::constants::pi<double>() << std::endl ;
std::cout << piFunc() << std::endl;
}
C++2a pi_v
In C++2a we should get pi_v:
#include <numbers>
#include <iostream>
int main() {
std::cout<< std::numbers::pi_v<double> <<"\n";
}