Как использовать константу PI в C++
Я хочу использовать константу PI и тригонометрические функции в некоторой программе на C++. Я получаю тригонометрические функции с include <math.h>
. Однако в этом заголовочном файле, похоже, нет определения для PI.
Как я могу получить PI без определения его вручную?
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.
*/
:
на новых платформы (по крайней мере, на моем 64-битном Ubuntu 14.04) мне не нужно определять
_USE_MATH_DEFINES
-
на (последних) платформах Linux есть
long double
значения также предоставляются как расширение GNU:# define M_PIl 3.141592653589793238462643383279502884L /* pi */
вы также можете использовать boost, который определяет важные математические константы с максимальной точностью для запрашиваемого типа (т. е. float vs double).
const double pi = boost::math::constants::pi<double>();
Проверьте увеличить документации для получения дополнительных примеров.
получите его от Блока 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 страница математики.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)));
Я не набрав π с необходимой точностью. Что это значит? The точность вам нужна точность 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
на math.h
.
вы можете сделать это:
#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.h.
значения, такие как 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;
}