我想在某些C ++程序中使用PI常数和三角函数。我得到的三角函数include <math.h>
。但是,此头文件中似乎没有PI的定义。
如何在不手动定义的情况下获取PI?
我想在某些C ++程序中使用PI常数和三角函数。我得到的三角函数include <math.h>
。但是,此头文件中似乎没有PI的定义。
如何在不手动定义的情况下获取PI?
Answers:
在某些(尤其是较旧的)平台上(请参见下面的评论),您可能需要
#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_DEFINES
在(最新)Linux平台上,还long double
提供了作为GNU扩展的值:
# define M_PIl 3.141592653589793238462643383279502884L /* pi */
#define _USE_MATH_DEFINES
然后在Visual C ++中进行#include <math.h>
定义M_PI
。谢谢。
cmath
代替math.h
。
_USE_MATH_DEFINES
GCC是否抱怨这是因为__STRICT_ANSI__
定义了(也许您通过-pedantic
或-std=c++11
)而不允许M_PI
定义,因此用来取消定义-D__STRICT_ANSI__
。自己定义它时,因为它是C ++,而不是宏,所以应该constexpr auto M_PI = 3.14159265358979323846;
。
Pi可以计算为atan(1)*4
。您可以通过这种方式计算值并将其缓存。
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
(大致而言)时有效。我不会打赌。正常,并使用原始文字定义常量。为什么在不需要时失去精度?
atan2(0, -1);
。
atan
不是constexpr
。
acos(-1)
,不需要atan2
。
您也可以使用boost,它可以为请求的类型(即float与double)定义最大精度的重要数学常数。
const double pi = boost::math::constants::pi<double>();
查看boost文档以获得更多示例。
not gonna use libs
者是一种害虫,可能是使用C ++编写不良软件的第一原因。
而是从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;
const
a设置为constexpr
。
constexpr
。
而不是写作
#define _USE_MATH_DEFINES
我建议使用-D_USE_MATH_DEFINES
或/D_USE_MATH_DEFINES
取决于您的编译器。
这样可以确保即使在有人在执行操作之前包括头的情况下(并且没有#define),您仍将拥有常量,而不是费时费力才能找到的晦涩的编译器错误。
<cmath>
在不同的地方使用它,将是一个很大的痛苦(尤其是(如果它包含在另一个库中,则包括在内)。如果他们把那部分放到头球后卫的本来会好得多,但是现在不能做太多事情了。实际上,编译器指令运行良好。
由于官方标准库没有定义常量PI,因此您必须自己定义它。因此,您的问题“如何在不手动定义PI的情况下获得PI”的答案是?是“您不-或您依赖于某些编译器特定的扩展。”。如果您不担心可移植性,可以查看编译器手册。
C ++允许您编写
const double PI = std::atan(1.0)*4;
但是此常数的初始化不能保证是静态的。但是,G ++编译器将这些数学函数作为内在函数进行处理,并能够在编译时计算该常数表达式。
4*atan(1.)
:atan
易于实现,乘以4是精确的操作。当然,现代编译器会以所需的精度来折叠(目标是折叠)所有常量,并且使用acos(-1)
甚至std::abs(std::arg(std::complex<double>(-1.,0.)))
是欧拉公式的倒数都是完全合理的,因此比看上去更美观(我添加了abs
因为我没有记得复杂的平面是如何切割的,或者根本没有定义)。
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
C ++ 20 std::numbers::pi
最后,它到达了:http : //eel.is/c++draft/numbers
我希望用法是这样的:
#include <numbers>
#include <iostream>
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]中,
<math>
需要添加新的标题。[...]
namespace std { namespace math { template<typename T > inline constexpr T pi_v = unspecified; inline constexpr double pi = pi_v<double>;
std::numbers::e
当然也有一个:-) 如何在C ++中计算欧拉常数或欧拉函数?
这些常量使用C ++ 14变量模板功能:C ++ 14变量模板:它们的用途是什么?有用法示例吗?
在该草案的早期版本中,该常量位于std::math::pi
:http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf
我会做
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
。因此,只需输入的精度long double
,即
template<typename T>
T const pi = static_cast<T>(/* long double precision π */);
但是您真的知道吗,将来在标准中将不会有比精度更高的新浮点类型。 long double
吗?你不知道
这就是第一个解决方案很漂亮的原因。您可以肯定,该标准将使一种新类型的三角函数超载。
而且,请不要说初始化时对三角函数的求值是性能的损失。
arg(log(x)) == π
所有0 < x < 1
。
我在涵盖所有基础的项目中的一个常见标头之一中使用以下代码:
#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 ++才需要的#define _USE_MATH_DEFINES。
x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+
M_PI
无需_USE_MATH_DEFINES
我刚看过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>
像M_PI,M_PI_2,M_PI_4之类的值不是标准C ++,因此constexpr似乎是一个更好的解决方案。可以制定出不同的const表达式来计算相同的pi,这关系到我(是否)(全部)为我提供完整的准确性。C ++标准未明确提及如何计算pi。因此,我倾向于使用手动定义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;
}
在Windows(cygwin + g ++)上,我发现有必要-D_XOPEN_SOURCE=500
为预处理器添加标志以处理M_PI
in 的定义math.h
。
M_PI
在特定平台上工作所需的步骤。那不再是对其他平台答案的评论,而对于其他平台的答案就是对这个平台的评论。
C ++ 14让您做到 static constexpr auto pi = acos(-1);
std::acos
不是constexpr
。因此,您的代码将无法编译。
acos
它不在constexpr
C ++ 14中,并且constexpr
甚至没有提议在C ++ 17中变成
constexpr
?显然不是:stackoverflow.com/questions/17347935/constexpr-math-functions
constexpr
,请参见例如(github.com/kthohr/gcem)。但是它们不与同名的C函数向后兼容,因此它们不能接管旧名称。
一些优雅的解决方案。我怀疑三角函数的精度是否等于类型的精度。对于那些喜欢写一个常数的人,这适用于g ++:-
template<class T>
class X {
public:
static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}
256个十进制数字精度对于任何将来的long long long double类型都应该足够。如果需要更多信息,请访问https://www.piday.org/million/。
您可以使用:
#define _USE_MATH_DEFINES // for C++
#include <cmath>
#define _USE_MATH_DEFINES // for C
#include <math.h>
标准C / C ++中未定义数学常数。要使用它们,您必须先定义_USE_MATH_DEFINES
然后包含cmath
或math.h
。
3.14
,3.141592
以及atan(1) * 4
?