如何在 C++ 中使用 PI 常量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1727881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:01:54  来源:igfitidea点击:

How to use the PI constant in C++

c++trigonometry

提问by Etan

I want to use the PI constant and trigonometric functions in some C++ program. I get the trigonometric functions with include <math.h>. However, there doesn't seem to be a definition for PI in this header file.

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

How can I get PI without defining it manually?

如何在不手动定义的情况下获得 PI?

回答by Ferenc Deak

On some (especially older) platforms (see the comments below) you might need to

在某些(尤其是较旧的)平台上(请参阅下面的评论),您可能需要

#define _USE_MATH_DEFINES

and then include the necessary header file:

然后包含必要的头文件:

#include <math.h>

and the value of pi can be accessed via:

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

M_PI

In my math.h(2014) it is defined as:

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

# define M_PI           3.14159265358979323846  /* pi */

but check your math.hfor more. An extract from the "old" math.h(in 2009):

但检查你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.
 */

However:

然而:

  1. on newer platforms (at least on my 64 bit Ubuntu 14.04) I do not need to define the _USE_MATH_DEFINES

  2. On (recent) Linux platforms there are long doublevalues too provided as a GNU Extension:

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */
    
  1. 在较新的平台上(至少在我的 64 位 Ubuntu 14.04 上)我不需要定义 _USE_MATH_DEFINES

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

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */
    

回答by Konamiman

Pi can be calculated as atan(1)*4. You could calculate the value this way and cache it.

Pi 可以计算为atan(1)*4。您可以通过这种方式计算值并将其缓存。

回答by BuschnicK

You could also use boost, which defines important math constants with maximum accuracy for the requested type (i.e. float vs double).

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

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

Check out the boost documentationfor more examples.

查看boost 文档以获取更多示例。

回答by Henrik

Get it from the FPU unit on chip instead:

从芯片上的 FPU 单元获取它:

double get_PI()
{
    double pi;
    __asm
    {
        fldpi
        fstp pi
    }
    return pi;
}

double PI = get_PI();

回答by Alex

I would recommend just typing in pi to the precision you need. This would add no calculation time to your execution, and it would be portable without using any headers or #defines. Calculating acos or atan is always more expensive than using a precalculated value.

我建议只输入 pi 到您需要的精度。这不会为您的执行增加计算时间,并且无需使用任何标题或 #defines 即可移植。计算 acos 或 atan 总是比使用预先计算的值更昂贵。

const double PI  =3.141592653589793238463;
const float  PI_F=3.14159265358979f;

回答by Matthieu M.

Rather than writing

而不是写作

#define _USE_MATH_DEFINES

I would recommend using -D_USE_MATH_DEFINESor /D_USE_MATH_DEFINESdepending on your compiler.

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

This way you are assured that even in the event of someone including the header before you do (and without the #define) you will still have the constants instead of an obscure compiler error that you will take ages to track down.

通过这种方式,您可以放心,即使有人在您这样做之前(并且没有 #define)包含了标头,您仍然会拥有常量,而不是您需要花费很长时间才能找到的晦涩编译器错误。

回答by sellibitze

Since the official standard library doesn't define a constant PI you would have to define it yourself. So the answer to your question "How can I get PI without defining it manually?" is "You don't -- or you rely on some compiler-specific extensions.". If you're not concerned about portability you could check your compiler's manual for this.

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

C++ allows you to write

C++ 允许你写

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

but the initialization of this constant is not guaranteed to be static. The G++ compiler however handles those math functions as intrinsics and is able to compute this constant expression at compile-time.

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

回答by Joakim

From the Posix man page of math.h:

math.hPosix 手册页

   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

回答by RichieHindle

Standard C++ doesn't have a constant for PI.

标准 C++ 没有用于 PI 的常量。

Many C++ compilers define M_PIin cmath(or in math.hfor C) as a non-standard extension. You may have to #define _USE_MATH_DEFINESbefore you can see it.

许多 C++ 编译器将M_PIin cmath(或 in math.hfor C)定义为非标准扩展。您可能必须#define _USE_MATH_DEFINES先看到它。

回答by 0xbadf00d

I would do

我会做

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

or

或者

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

I would nottyping in π to the precision you need. What is that even supposed to mean? The precision you needis the precision of T, but we know nothing about T.

不会输入 π 到您需要的精度。这到底是什么意思?在你需要的精度是精度T,但我们并不知道T

You might say: What are you talking about? Twill be float, doubleor long double. So, just type in the precision of long double, i.e.

你可能会说:你在什么?Tfloatdoublelong double。所以,只需输入精度long double,即

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

But do you really know that there won't be a new floating point type in the standard in the future with an even higher precision than long double? You don't.

但是你真的知道未来标准中不会有比 精度更高的新浮点类型long double吗?你没有。

And that's why the first solution is beautiful. You can be quite sure that the standard would overload the trigonometric functions for a new type.

这就是为什么第一个解决方案很漂亮的原因。您可以非常确定标准会为新类型重载三角函数。

And please, don't say that the evaluation of a trigonometric function at initialization is a performance penalty.

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