Best platform independent pi constant?

后端 未结 2 505
温柔的废话
温柔的废话 2020-12-18 23:39

I know that you can use:

#define _USE_MATH_DEFINES

and then:

M_PI

to get the constant pi. However, if I r

相关标签:
2条回答
  • 2020-12-19 00:00

    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;
    }
    
    0 讨论(0)
  • 2020-12-19 00:14

    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";
    }
    
    0 讨论(0)
提交回复
热议问题