Cómo usar la constante PI en C ++

Quiero usar las funciones constantes y trigonométricas de PI en algún progtwig C ++. Obtengo las funciones trigonométricas con include . Sin embargo, no parece haber una definición para PI en este archivo de encabezado.

¿Cómo puedo obtener PI sin definirlo manualmente?

En algunas plataformas (especialmente antiguas) (ver los comentarios a continuación) es posible que necesite

 #define _USE_MATH_DEFINES 

y luego incluir el archivo de encabezado necesario:

 #include  

y se puede acceder al valor de pi a través de:

 M_PI 

En mi math.h (2014) se define como:

 # define M_PI 3.14159265358979323846 /* pi */ 

pero revisa tus math.h para math.h más. Un extracto del “viejo” math.h (en 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. */ 

Sin embargo:

  1. en las plataformas más nuevas (al menos en mi Ubuntu 14.04 de 64 bits) no necesito definir el _USE_MATH_DEFINES

  2. En las plataformas Linux (recientes), también se proporcionan valores long double como una extensión GNU:

     # define M_PIl 3.141592653589793238462643383279502884L /* pi */ 

Pi se puede calcular como atan(1)*4 . Puede calcular el valor de esta manera y almacenarlo en caché.

También podría usar boost, que define constantes matemáticas importantes con la máxima precisión para el tipo solicitado (es decir, float contra double).

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

Consulte la documentación de impulso para obtener más ejemplos.

Obtenlo de la unidad FPU en chip:

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

Yo recomendaría simplemente escribir en pi con la precisión que necesita. Esto no agregaría tiempo de cálculo a su ejecución, y sería portátil sin usar encabezados o #defines. Calcular acos o atan siempre es más costoso que usar un valor precalculado.

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

En lugar de escribir

 #define _USE_MATH_DEFINES 

Yo recomendaría usar -D_USE_MATH_DEFINES o /D_USE_MATH_DEFINES dependiendo de tu comstackdor.

De esta forma, puede estar seguro de que, incluso en el caso de que alguien incluya el encabezado antes que usted (y sin #definir), tendrá las constantes en lugar de un oscuro error del comstackdor que tardará en rastrear.

Dado que la biblioteca estándar oficial no define un PI constante, tendría que definirlo usted mismo. Entonces, la respuesta a su pregunta “¿Cómo puedo obtener PI sin definirlo manualmente?” es “No lo hace, o depende de algunas extensiones específicas del comstackdor”. Si no le preocupa la portabilidad, puede consultar el manual del comstackdor para esto.

C ++ te permite escribir

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

pero la inicialización de esta constante no se garantiza que sea estática. Sin embargo, el comstackdor de G ++ maneja esas funciones matemáticas como intrínsecas y puede calcular esta expresión constante en tiempo de comstackción.

De la página del hombre de Posix de math.h :

  The  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 

El estándar C ++ no tiene una constante para PI.

Muchos comstackdores de C ++ definen M_PI en cmath (o en math.h para C) como una extensión no estándar. Es posible que #define _USE_MATH_DEFINES antes de poder verlo.

yo lo haría

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

o

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

No escribiría π en la precisión que necesita . ¿Qué se supone que significa eso? La precisión que necesita es la precisión de T , pero no sabemos nada de T

Usted podría decir: ¿De qué estás hablando? T será float , double o long double . Entonces, solo escriba la precisión del long double , es decir

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

Pero, ¿realmente sabe que no habrá un nuevo tipo de coma flotante en el estándar en el futuro con una precisión aún mayor que el long double ? Tu no

Y es por eso que la primera solución es hermosa. Puede estar bastante seguro de que el estándar sobrecargaría las funciones trigonométricas para un nuevo tipo.

Y por favor, no diga que la evaluación de una función trigonométrica en la inicialización es una penalización de rendimiento.

Generalmente prefiero definir el mío: const double PI = 2*acos(0.0); porque no todas las implementaciones lo proporcionan por usted.

La cuestión de si esta función se llama durante el tiempo de ejecución o está estática en tiempo de comstackción no suele ser un problema, ya que solo ocurre una vez.

Utilizo follow en uno de mis encabezados comunes en el proyecto que cubre todas las bases:

 #define _USE_MATH_DEFINES #include  #ifndef M_PI #define M_PI (3.14159265358979323846) #endif #ifndef M_PIl #define M_PIl (3.14159265358979323846264338327950288) #endif 

En una nota lateral, todos los comstackdores a continuación definen las constantes M_PI y M_PIl si incluye . No es necesario agregar `#define _USE_MATH_DEFINES que solo es necesario para VC ++.

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

Acabo de encontrar este artículo de Danny Kalev que tiene un gran consejo para C ++ 14 en adelante.

 template constexpr T pi = T(3.1415926535897932385); 

Pensé que esto era muy bueno (aunque usaría el PI de mayor precisión que pudiera), especialmente porque las plantillas pueden usarlo según el tipo.

 template T circular_area(T r) { return pi * r * r; } double darea= circular_area(5.5);//uses pi float farea= circular_area(5.5f);//uses pi 

En Windows (cygwin + g ++), he encontrado necesario agregar el indicador -D_XOPEN_SOURCE=500 para que el preprocesador procese la definición de M_PI en math.h

C ++ 14 le permite hacer static constexpr auto pi = acos(-1);

Puedes hacerlo:

 #include  #ifndef M_PI #define M_PI (3.14159265358979323846) #endif 

Si M_PI ya está definido en cmath , esto no hará nada más que incluir cmath . Si M_PI no está definido (que es el caso, por ejemplo, en Visual Studio), lo definirá. En ambos casos, puede usar M_PI para obtener el valor de pi.

Este valor de pi proviene de qmath.h de Qt Creator.

Los valores como M_PI, M_PI_2, M_PI_4, etc. no son C ++ estándar, por lo que un constexpr parece una mejor solución. Se pueden formular diferentes expresiones const que calculen el mismo pi y me preocupa si (todas) me proporcionan la precisión completa. El estándar de C ++ no menciona explícitamente cómo calcular pi. Por lo tanto, tiendo a volver a definir pi manualmente. Me gustaría compartir la solución a continuación, que admite todo tipo de fracciones de pi con total precisión.

 #include  #include  template constexpr double dpipart() { long double const pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899863; return static_cast(pi * RATIO::num / RATIO::den); } int main() { std::cout << dpipart>() << std::endl; }