Cómo usar la constante PI en C++


Quiero usar la constante PI y las funciones trigonométricas en algún programa de C++. Obtengo las funciones trigonométricas con include <math.h>. Sin embargo, no parece haber una definición para PI en este archivo de encabezado.

¿Cómo puedo obtener PI sin definirla manualmente?

Author: Yu Hao, 2009-11-13

17 answers

En algunas plataformas (especialmente las más antiguas) (consulte los comentarios a continuación) es posible que necesite

#define _USE_MATH_DEFINES

Y luego incluir el archivo de cabecera necesario:

#include <math.h>

Y el valor de pi se puede acceder a través de:

M_PI

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

# define M_PI           3.14159265358979323846  /* pi */

Pero revisa tu math.h para 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 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) hay long double valores también proporcionados como una extensión GNU:

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */
    
 435
Author: fritzone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-25 06:54:21

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

 151
Author: Konamiman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-13 08:26:27

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 vs double).

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

Echa un vistazo a la documentación de boost para más ejemplos.

 102
Author: BuschnicK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-13 12:33:29

Obtenerlo de la unidad FPU en el chip en su lugar:

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

double PI = get_PI();
 53
Author: Henrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-04 15:01:45

Recomendaría simplemente escribir en pi con la precisión que necesita. Esto no añadiría tiempo de cálculo a su ejecución, y sería portable sin usar ninguna cabecera o #define. 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;
 48
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-19 05:40:48

En lugar de escribir

#define _USE_MATH_DEFINES

Recomendaría usar -D_USE_MATH_DEFINES o /D_USE_MATH_DEFINES dependiendo de su compilador.

De esta manera se asegura de que incluso en el caso de que alguien incluya la cabecera antes que usted (y sin el #define), todavía tendrá las constantes en lugar de un error oscuro del compilador que tardará años en rastrear.

 38
Author: Matthieu M.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-13 12:09:42

Dado que la biblioteca estándar oficial no define una PI constante, tendría que definirla usted mismo. Así que la respuesta a su pregunta " ¿Cómo puedo obtener PI sin definirlo manualmente?"es "no-o que dependen de algún compilador de extensiones específicas.". Si no está preocupado por la portabilidad, puede consultar el manual de su compilador para esto.

C++ le permite escribir

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

Pero no se garantiza que la inicialización de esta constante sea estática. El compilador G++ sin embargo, maneja esas funciones matemáticas como intrínsecas y es capaz de calcular esta expresión constante en tiempo de compilación.

 36
Author: sellibitze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-13 08:37:38

De la página man de Posix de 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
 28
Author: Joakim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-14 21:26:49

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

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

 24
Author: RichieHindle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-13 08:27:24

Yo haría

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

O

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

Yo no escribiendo π con la precisión que necesita . ¿Qué se supone que significa eso? La precisión que necesitas es la precisión de T, pero no sabemos nada sobre T.

Podrías decir: ¿De qué estás hablando? T será float, double o long double. Por lo tanto, simplemente escriba la precisión de long double, es decir,

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

Pero ¿realmente sabes que no habrá una nueva flotación tipo de punto en el estándar en el futuro con una precisión aún mayor que long double? No lo haces.

Y es por eso que la primera solución es hermosa. Puede estar 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.

 11
Author: 0xbadf00d,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-14 14:23:22

Generalmente prefiero definir mi propio: const double PI = 2*acos(0.0); porque no todas las implementaciones lo proporcionan para usted.

La cuestión de si esta función es llamada en tiempo de ejecución o es estática en tiempo de compilación no suele ser un problema, porque solo sucede una vez de todos modos.

 8
Author: Sumudu Fernando,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-18 04:03:41

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

#define _USE_MATH_DEFINES
#include <cmath>

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

#ifndef M_PIl
#define M_PIl (3.14159265358979323846264338327950288)
#endif

En una nota al margen, todos los compiladores siguientes definen constantes M_PI y M_PIl si se incluye <cmath>. No es necesario añadir ` # define _USE_MATH_DEFINES que solo es necesario para VC++.

x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+
 7
Author: ShitalShah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-13 15:16:58

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

template<typename T>
constexpr T pi = T(3.1415926535897932385);

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

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
Author: Beta Jester,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-27 01:50:09

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

 2
Author: Papa Smurf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-15 12:36:44

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

 2
Author: Willy Goat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-21 20:09:45

Puedes hacer esto:

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

Si M_PI ya está definido en cmath, esto no hará otra cosa 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 del creador de Qt.h.

 1
Author: Donald Duck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 11:53:14

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 calculan el mismo pi y me preocupa si (todas) me proporcionan la precisión completa. El estándar C++ no menciona explícitamente cómo calcular pi. Por lo tanto, tiendo a recurrir a la definición de 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 <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;
}
 0
Author: Jeroen Lammertink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-31 08:49:13