代码之家  ›  专栏  ›  技术社区  ›  Etan bbum

如何在C++中使用π常数

  •  392
  • Etan bbum  · 技术社区  · 16 年前

    我想在一些C++程序中使用π常数和三角函数。我得到三角函数 include <math.h> . 但是,这个头文件中似乎没有PI的定义。

    如何在不手动定义的情况下获取pi?

    17 回复  |  直到 7 年前
        1
  •  459
  •   Ferenc Deak    12 年前

    在某些(特别是较旧的)平台上(请参阅下面的注释),您可能需要

    #define _USE_MATH_DEFINES
    

    然后包括必要的头文件:

    #include <math.h>
    

    pi的值可以通过以下方式访问:

    M_PI
    

    在我的 math.h (2014)定义为:

    # define M_PI           3.14159265358979323846  /* pi */
    

    但是检查一下你的 数学,h 更多。摘自《旧约》 数学,h (2009):

    /* Define _USE_MATH_DEFINES before including math.h to expose these macro
     * definitions for common math constants.  These are placed under an #ifdef
     * since these commonly-defined names are not part of the C/C++ standards.
     */
    

    然而:

    1. 在较新的平台上(至少在64位Ubuntu 14.04上),我不需要定义 _USE_MATH_DEFINES

    2. 在(最近的)Linux平台上有 long double 值也作为GNU扩展提供:

      # define M_PIl          3.141592653589793238462643383279502884L /* pi */
      
        2
  •  161
  •   Konamiman    16 年前

    pi可计算为 atan(1)*4 . 您可以这样计算值并缓存它。

        3
  •  104
  •   BuschnicK    16 年前

    您还可以使用Boost,它为所请求的类型(即float与double)定义具有最大精度的重要数学常量。

    const double pi = boost::math::constants::pi<double>();
    

    查看 boost documentation 更多示例。

        4
  •  59
  •   Henrik    10 年前

    从芯片上的FPU单元获取:

    double get_PI()
    {
        double pi;
        __asm
        {
            fldpi
            fstp pi
        }
        return pi;
    }
    
    double PI = get_PI();
    
        5
  •  46
  •   Francisco Presencia    12 年前

    我建议您按需要的精度输入pi。这不会给您的执行增加任何计算时间,并且可以在不使用任何头或定义的情况下进行移植。计算acos或atan总是比使用预先计算的值更昂贵。

    const double PI  =3.141592653589793238463;
    const float  PI_F=3.14159265358979f;
    
        6
  •  41
  •   Matthieu M.    16 年前

    而不是写作

    #define _USE_MATH_DEFINES
    

    我建议使用 -D_USE_MATH_DEFINES /D_USE_MATH_DEFINES 取决于编译器。

    这样,您就可以确保,即使在执行此操作之前有人包括头文件(并且没有定义),您仍将拥有常量,而不是一个模糊的编译器错误,您需要花费很多时间来跟踪。

        7
  •  37
  •   sellibitze    16 年前

    因为官方标准库没有定义常量pi,所以您必须自己定义它。所以你的问题的答案是,“我怎样才能得到圆周率而不需要手动定义?”是“您不需要——或者您依赖于某些特定于编译器的扩展”。如果您不关心可移植性,您可以查看编译器的手册。

    C++允许你编写

    const double PI = std::atan(1.0)*4;
    

    但是这个常量的初始化并不能保证是静态的。然而,G++编译器将这些数学函数作为内部函数来处理,并且能够在编译时计算这个常量表达式。

        8
  •  28
  •   yiati    12 年前

    Posix man page of math.h :

       The  <math.h>  header  shall  provide for the following constants.  The
       values are of type double and are accurate within the precision of  the
       double type.
    
       M_PI   Value of pi
    
       M_PI_2 Value of pi/2
    
       M_PI_4 Value of pi/4
    
       M_1_PI Value of 1/pi
    
       M_2_PI Value of 2/pi
    
       M_2_SQRTPI
              Value of 2/ sqrt pi
    
        9
  •  24
  •   RichieHindle    16 年前

    标准C++对PI没有常数。

    许多C++编译器定义 M_PI 在里面 cmath (或) math.h c)作为非标准扩展。你可能不得不 #define _USE_MATH_DEFINES 在你看到它之前。

        10
  •  13
  •   0xbadf00d    10 年前

    我愿意

    template<typename T>
    T const pi = std::acos(-T(1));
    

    template<typename T>
    T const pi = std::arg(-std::log(T(2)));
    

    我愿意 按您需要的精度键入 . 这到底是什么意思?这个 你需要的精确性 是的精度 T 但是我们对 T .

    你可以说: 你在说什么? T float , double long double .所以,只要输入 长双倍 ,即

    template<typename T>
    T const pi = static_cast<T>(/* long double precision π */);
    

    但是你真的知道标准中不会有一个新的浮点类型,它的精度比 长双倍 是吗?你没有。

    这就是为什么第一个解决方案是漂亮的。您可以非常肯定,对于一个新类型,该标准将重载三角函数。

    请不要说初始化时对三角函数的评估是一种性能损失。

        11
  •  8
  •   Sumudu Fernando    16 年前

    我通常喜欢定义自己的: const double PI = 2*acos(0.0); 因为并不是所有的实现都为您提供它。

    这个函数是在运行时被调用,还是在编译时被静态调用,这通常不是一个问题,因为它无论如何只发生一次。

        12
  •  8
  •   Chris Nolet Chen_Wayne    9 年前

    我在项目中的一个常见标题中使用了以下内容,该标题涵盖了所有基础:

    #define _USE_MATH_DEFINES
    #include <cmath>
    
    #ifndef M_PI
    #define M_PI (3.14159265358979323846)
    #endif
    
    #ifndef M_PIl
    #define M_PIl (3.14159265358979323846264338327950288)
    #endif
    

    附带说明的是,下面的所有编译器都定义m_pi和m_pil常量,如果您包括 <cmath> . 不需要添加“定义”使用“数学”定义,这只对VC++是必需的。

    x86 GCC 4.4+
    ARM GCC 4.5+
    x86 Clang 3.0+
    
        13
  •  5
  •   dbc    8 年前

    我刚遇到 this article 通过 Danny Kalev 对于C++ 14和UP有很好的提示。

    template<typename T>
    constexpr T pi = T(3.1415926535897932385);
    

    我觉得这很酷(尽管我会使用那里最高精度的pi),尤其是因为模板可以基于类型使用它。

    template<typename T>
    T circular_area(T r) {
      return pi<T> * r * r;
    }
    double darea= circular_area(5.5);//uses pi<double>
    float farea= circular_area(5.5f);//uses pi<float>
    
        14
  •  2
  •   A.L    11 年前

    在Windows(cygwin+g++)上,我发现有必要添加标志 -D_XOPEN_SOURCE=500 用于预处理器处理 M_PI 在里面 math.h .

        15
  •  2
  •   Willy Goat    10 年前

    C++ 14让你做 static constexpr auto pi = acos(-1);

        16
  •  2
  •   Jeroen Lammertink    7 年前

    像MyPI、MyPix2、MyPIY4等的值不是标准的C++,所以SCONExPR似乎是一个更好的解决方案。不同的常量表达式可以用来计算相同的圆周率,这关系到它们(全部)是否能提供完全的精度。C++标准没有明确提到如何计算PI。因此,我倾向于回到手工定义pi。我想分享下面的解决方案,它支持圆周率的所有分数的完全精度。

    #include <ratio>
    #include <iostream>
    
    template<typename RATIO>
    constexpr double dpipart()
    {
        long double const pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899863;
        return static_cast<double>(pi * RATIO::num / RATIO::den);
    }
    
    int main()
    {
        std::cout << dpipart<std::ratio<-1, 6>>() << std::endl;
    }
    
        17
  •  1
  •   Donald Duck user7392049    9 年前

    您可以这样做:

    #include <cmath>
    #ifndef M_PI
    #define M_PI (3.14159265358979323846)
    #endif
    

    如果 M_PI 已在中定义 cmath ,除了包含 数学库 .如果 MYPI 没有定义(例如在Visual Studio中就是这样),它将定义它。在这两种情况下,您都可以使用 MYPI 得到π的值。

    pi的这个值来自qt creator的qmath.h。