Как использовать константу PI в C++



Я хочу использовать константу PI и тригонометрические функции в некоторых программах на C++. Я получаю тригонометрические функции с include <math.h>. Однако в этом заголовочном файле, похоже, нет определения для PI.



Как я могу получить PI, не определяя его вручную?

16402   17  

17 ответов:

на некоторых (особенно старых) платформах (см. комментарии ниже) вам может понадобиться

#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.
 */
:
  1. на новых платформы (по крайней мере, на моем 64-битном Ubuntu 14.04) мне не нужно определять _USE_MATH_DEFINES

  2. на (последних) платформах 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<double>();

Проверьте boost documentation для получения дополнительных примеров.

получить его от Блока 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, не определяя его вручную?"is" вы не ... Или вы полагаетесь на некоторые расширения, специфичные для компилятора.". Если вы не беспокоитесь о переносимости, вы можете проверить руководство вашего компилятора для этого.

C++ позволяет писать

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

но инициализация этой константы не гарантируется статичностью. Этот Однако компилятор G++ обрабатывает эти математические функции как внутренние и может вычислить это постоянное выражение во время компиляции.

С 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

стандартный C++ не имеет константы для PI.

многие компиляторы C++ определяют M_PI на cmath (или math.h для C) как нестандартное расширение. Возможно, вам придется #define _USE_MATH_DEFINES прежде чем вы можете увидеть его.

Я бы сделал

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? А ты нет.

и именно поэтому первое решение красиво. Вы можете быть совершенно уверены, что стандарт перегрузит тригонометрические функции для нового типа.

и, пожалуйста, не говорите, что оценка тригонометрической функции при инициализации производительности штраф.

Я вообще предпочитаю определять свой собственный: const double PI = 2*acos(0.0); потому что не все реализации предоставляют его для вас.

вопрос о том, вызывается ли эта функция во время выполнения или статична во время компиляции, обычно не является проблемой, потому что это происходит только один раз в любом случае.

Я использую следующее в одном из моих общих заголовков в проекте, который охватывает все базы:

#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>. Нет необходимости добавлять ' #define _USE_MATH_DEFINES, который требуется только для VC++.

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

Я только что наткнулся в этой статье by Дэнни Калев который имеет большой совет для 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>

на windows (cygwin + g++), я нашел необходимым добавить флаг -D_XOPEN_SOURCE=500 для препроцессора для обработки определения M_PI in math.h.

C++14 позволяет сделать static constexpr auto pi = acos(-1);

вы можете сделать это:

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

если M_PI уже определен в cmath, это не будет делать ничего, кроме включения cmath. Если M_PI Не определен (что имеет место, например, в Visual Studio), он определит его. В обоих случаях, вы можете использовать M_PI чтобы получить значение pi.

это значение pi происходит от qmath Qt Creator.з.

значения, такие как 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;
}

Comments

    Ничего не найдено.