最好的跨平台 pi 常数是什么?

13

我知道你可以使用:

#define _USE_MATH_DEFINES

然后:

M_PI

如何获得常数 pi,但如果我没记错的话(欢迎评论),这取决于编译器/平台。那么,在将其从 Linux 移植到其他系统时,最可靠的使用 pi 常数的方法是什么?

我知道我可以定义一个浮点数/双精度浮点数,然后将其设置为四舍五入的 pi 值,但我真的想知道是否有指定的机制。


2
如果它是平台相关的,那么每个平台都应该为这些宏提供适当的值,不是吗? - Pointy
我认为唯一真正平台无关的方法是 atan(1.0)*4.0 - Nicu Stiurca
应该是这样的,但它真的是吗? ;) - Draugr
2个回答

14

Meeting C++有一篇关于生成圆周率的不同选项的文章:C++ & π。他们讨论了一些选项,其中包括cmath,但它并不是跨平台的:

double pi = M_PI;
std::cout << pi << std::endl;

并来自boost

std::cout << boost::math::constants::pi<double>() << std::endl

使用atan,并移除constexpr,因为正如SchighSchagh所指出的那样,这不是平台无关的。

 double const_pi() { return std::atan(1)*4; }

我将所有方法汇总到了一个实时示例中:
#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

在C++2a中,我们应该得到pi_v

#include <numbers>
#include <iostream>

int main() {
     std::cout<< std::numbers::pi_v<double> <<"\n";
}

谢谢,我认为这已经足够可靠满足我的需求了。不过我会考虑集成boost,因为我想尝试一些其他的功能。 - Draugr
@Draugr,你可以尝试使用一些在线C++编译器,比如boost。我在我的回答中也添加了一个实时示例。 - Shafik Yaghmour
@SchighSchagh 请查看此处是否符合编译器扩展规范,将非constexpr标准库函数视为constexpr以获取更多细节。 - Shafik Yaghmour
_v 部分是否与 is_same_v 中的 _v 相同,其他可能意味着“值”? - Ayxan Haqverdili

3
下面的函数不依赖于任何库即可计算pi。
同时,其结果类型是一个模板参数。
由于它只能使用固定精度分数类型 - 计算值需要在2次迭代中收敛并保持恒定,因此平台独立性受到了一些抑制。
因此,如果指定某种任意精度有理数或浮点类,并且该类将根据需要自动增加其精度,则调用此函数将无法正常结束。
#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;
}

非常感谢您提供这个建议,模板集成是一个非常好的想法。 - Draugr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接