Как использовать константу 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>();Проверьте 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++ обрабатывает эти математические функции как внутренние и может вычислить это постоянное выражение во время компиляции.
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_PIinmath.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.з.
значения, такие как 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