我想在一些C++程序中使用PI常量和三角函数.我得到了三角函数include
.但是,此头文件中似乎没有PI的定义.
如何在不手动定义PI的情况下获取PI?
在某些(特别是较旧的)平台上(请参阅下面的评论),您可能需要
#define _USE_MATH_DEFINES
然后包含必要的头文件:
#include
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_DEFINES
在(最近的)Linux平台上,还有long double
作为GNU扩展提供的值:
# define M_PIl 3.141592653589793238462643383279502884L /* pi */
Pi可以计算为atan(1)*4
.你可以用这种方式计算值并缓存它.
您还可以使用boost,它为所请求的类型定义了具有最大精度的重要数学常量(即float vs double).
const double pi = boost::math::constants::pi();
查看增强文档以获取更多示例.
从芯片上的FPU单元获取它:
double get_PI() { double pi; __asm { fldpi fstp pi } return pi; } double PI = get_PI();
我建议只需输入pi即可获得所需的精度.这将不会为您的执行增加计算时间,并且它可以在不使用任何标头或#defines的情况下移植.计算acos或atan总是比使用预先计算的值更昂贵.
const double PI =3.141592653589793238463; const float PI_F=3.14159265358979f;
而不是写作
#define _USE_MATH_DEFINES
我建议使用-D_USE_MATH_DEFINES
或/D_USE_MATH_DEFINES
取决于您的编译器.
通过这种方式,您可以确保即使在您执行之前包含标题的人(并且没有#define),您仍将拥有常量,而不是一个模糊的编译器错误,您需要花费很长时间才能跟踪.
由于官方标准库没有定义常量PI,因此您必须自己定义它.所以你的问题的答案是"如何在不手动定义PI的情况下获得PI?" 是"你没有 - 或者你依赖于一些特定于编译器的扩展." 如果您不关心可移植性,可以查看编译器的手册.
C++允许你写
const double PI = std::atan(1.0)*4;
但是这个常量的初始化并不保证是静态的.然而,G ++编译器将这些数学函数作为内在函数处理,并且能够在编译时计算此常量表达式.
从math.h的Posix手册页:
Theheader 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
标准C++没有PI的常量.
许多C++编译器定义M_PI
中cmath
(或在math.h
为C)作为非标准扩展.您可能必须#define _USE_MATH_DEFINES
先看到它.
我会做
templateT const pi = std::acos(-T(1));
要么
templateT const pi = std::arg(-std::log(T(2)));
我不会 输入π到你需要的精度.那甚至应该是什么意思?在你需要的精度是精度T
,但我们并不知道T
.
你可能会说:你在说什么?T
将是float
,double
或long double
.所以,只需键入精度long double
,即
templateT const pi = static_cast (/* long double precision ? */);
但是你真的知道未来标准中不会有新的浮点类型,其精度甚至高于long double
?你没有.
这就是为什么第一个解决方案很漂亮的原因.您可以确定该标准会使新类型的三角函数超载.
并且,请不要说在初始化时对三角函数的评估是性能损失.
C ++ 20 std::numbers::pi
最后,它到达了:http : //eel.is/c++draft/numbers
我希望用法是这样的:
#include#include int main() { std::cout << std::numbers::pi << std::endl; }
当GCC支持到达时,我会尝试一下,GCC 9.1.0 g++-9 -std=c++2a
仍然不支持它。
接受的提案描述:
5.0。“标题” [headers]在表[tab:cpp.library.headers]中,
需要添加新的标题。
[...]
namespace std { namespace math { templateinline constexpr T pi_v = unspecified; inline constexpr double pi = pi_v ;
std::numbers::e
当然也有一个:-) 如何在C ++中计算欧拉常数或欧拉函数?
这些常量使用C ++ 14变量模板功能:C ++ 14变量模板:它们的用途是什么?有用法示例吗?
在该草案的早期版本中,该常量位于std::math::pi
:http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf
我通常更喜欢定义自己的:const double PI = 2*acos(0.0);
因为并非所有实现都为您提供.
是否在运行时调用此函数或在编译时静态调出此函数的问题通常不是问题,因为它只会发生一次.
我在项目中的一个常见标题中使用了以下内容:
#define _USE_MATH_DEFINES #include#ifndef M_PI #define M_PI (3.14159265358979323846) #endif #ifndef M_PIl #define M_PIl (3.14159265358979323846264338327950288) #endif
另外,如果包含,下面的所有编译器都会定义M_PI和M_PIl常量
.不需要添加`#define _USE_MATH_DEFINES,这只是VC++所必需的.
x86 GCC 4.4+ ARM GCC 4.5+ x86 Clang 3.0+
我刚刚看到Danny Kalev 撰写的这篇文章,它对C++ 14及以上版本提出了很好的建议.
templateconstexpr T pi = T(3.1415926535897932385);
我觉得这很酷(虽然我会尽可能使用最高精度的PI),特别是因为模板可以根据类型使用它.
templateT circular_area(T r) { return pi * r * r; } double darea= circular_area(5.5);//uses pi float farea= circular_area(5.5f);//uses pi