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?
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:
En plataformas más nuevas (al menos en mi Ubuntu 14.04 de 64 bits) No necesito definir el
_USE_MATH_DEFINES
-
En las plataformas Linux (recientes) hay
long double
valores también proporcionados como una extensión GNU:# define M_PIl 3.141592653589793238462643383279502884L /* pi */
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é.
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.
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();
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;
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.
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.
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
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.
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.
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.
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+
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>
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
.
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);
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.
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;
}
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