我想在一些c++程序中使用PI常数和三角函数。我得到三角函数包含<math。h>。然而,在这个头文件中似乎没有PI的定义。

如何获得PI而不手动定义它?


当前回答

一些优雅的解决方案。不过,我怀疑三角函数的精度是否等于类型的精度。对于那些喜欢编写常量值的人来说,这适用于g++:-

template<class T>
class X {
public:
            static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}

256十进制数字的精度应该足以用于任何未来的长长长双精度类型。如果需要更多信息,请访问https://www.piday.org/million/。

其他回答

因为官方标准库没有定义常数PI,你必须自己定义它。因此,对于你的问题“如何获得PI而不手动定义它?”的答案是“你没有——或者你依赖于一些特定于编译器的扩展。”如果你不关心可移植性,你可以查看编译器手册。

c++允许你编写

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

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

你可以用它:

#define _USE_MATH_DEFINES // for C++
#include <cmath>

#define _USE_MATH_DEFINES // for C
#include <math.h>

在标准C/ c++中没有定义数学常数。要使用它们,必须首先定义_use_math_definitions,然后包括cmath或math.h。

我在项目中使用了一个覆盖所有基础的公共头文件:

#define _USE_MATH_DEFINES
#include <cmath>

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

#ifndef M_PIl
#define M_PIl (3.14159265358979323846264338327950288)
#endif

另外,如果包含<cmath>,下面所有的编译器都定义了M_PI和M_PIl常量。不需要添加只有vc++才需要的#define _use_math_definitions。

x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+

我刚刚看到了Danny Kalev写的一篇文章,它为c++ 14及以上版本提供了一个很好的建议。

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>

在一些(特别是旧的)平台上(参见下面的评论),您可能需要这样做

#define _USE_MATH_DEFINES

然后包含必要的头文件:

#include <math.h>

PI的值可以通过:

M_PI

在我的math.h(2014)中,它被定义为:

# define M_PI           3.14159265358979323846  /* pi */

但请检查math.h以获得更多信息。摘自“旧”math.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.
 */

然而:

在更新的平台上(至少在我的64位Ubuntu 14.04上),我不需要定义_use_math_definitions 在(最近的)Linux平台上,GNU扩展也提供了长double值: #定义M_PIl 3.141592653589793238462643383279502884L /* pi */