Как использовать константу PI в C ++ - PullRequest
408 голосов
/ 13 ноября 2009

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

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

Ответы [ 18 ]

8 голосов
/ 28 мая 2016

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

#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+
8 голосов
/ 18 ноября 2009

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

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

6 голосов
/ 27 января 2018

Я только что натолкнулся на эту статью Дэнни Калев , в которой есть отличный совет для 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>
4 голосов
/ 31 июля 2018

Такие значения, как M_PI, M_PI_2, M_PI_4 и т. Д. Не являются стандартными C ++, поэтому constexpr кажется лучшим решением. Могут быть сформулированы различные выражения const, которые вычисляют один и тот же пи, и меня интересует, обеспечивают ли они (все) полную точность. Стандарт C ++ явно не упоминает, как рассчитать число Пи. Поэтому я склоняюсь к определению числа «пи» вручную. Я хотел бы поделиться приведенным ниже решением, которое поддерживает все виды дробных чисел с полной точностью.

#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;
}
2 голосов
/ 21 марта 2016

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

2 голосов
/ 15 декабря 2014

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

1 голос
/ 09 ноября 2016

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

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

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

Это значение pi взято из qmath.h Создателя Qt.

0 голосов
/ 18 мая 2019

Некоторые элегантные решения. Я сомневаюсь, что точность тригонометрических функций равна точности типов. Для тех, кто предпочитает писать постоянное значение, это работает для 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/.

...