Hay un problema bastante tonto con el número pi en C y C ++. Hasta donde yo sé M_PI
definido en math.h
no es requerido por ningún estándar.
Los nuevos estándares de C ++ introdujeron muchas matemáticas complicadas en la biblioteca estándar: funciones hiperbólicas std::hermite
y std::cyl_bessel_i
diferentes generadores de números aleatorios, y así sucesivamente.
¿Alguno de los 'nuevos' estándares trajo una constante para pi? Si no, ¿por qué? ¿Cómo funciona toda esta complicada matemática sin ella?
Soy consciente de preguntas similares sobre pi en C ++ (tienen varios años y estándares de antigüedad); Me gustaría saber el estado actual del problema.
También estoy muy interesado en por qué oh por qué C ++ todavía no tiene una constante pi pero tiene muchas matemáticas más complicadas.
UPD: Sé que puedo definir pi yo mismo como 4 * atan (1) o acos (1) o doble pi = 3.14. Por supuesto. ¿Pero por qué en 2018 todavía tengo que hacerlo? ¿Cómo funcionan las funciones matemáticas estándar sin pi?
UPD2: Según este informe de viaje para la reunión del Comité C ++ en julio de 2019 en Colonia, la propuesta P0631 (constantes matemáticas) fue aceptada en C ++ 20. ¡Parece que por fin tendremos el número pi en la biblioteca estándar!
Respuestas:
Hasta C ++ 17 pi inclusive no es una constante introducida en el lenguaje, y es un dolor en el cuello.
Soy afortunado porque uso boost y definen pi con un número suficientemente grande de decimales para incluso 128 bits
long double
.Si no usa Boost, codifíquelo usted mismo. Definirlo con una función trigonométrica es tentador, pero si lo hace, no puede hacerlo
constexpr
. La precisión de las funciones trigonométricas tampoco está garantizada por ninguna norma know I de ( cf .std::sqrt
), Por lo que realmente está en un terreno peligroso de hecho depender de una función de este tipo.Hay una manera de obtener un
constexpr
valor para pi mediante metaprogramación: consulte http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/Desde C ++ 20 algunas buenas noticias. No es un defininition de pi . C ++ 20 agrega algunas constantes matemáticas en
<numbers>
. Por ejemplostd::numbers::pi
es undouble
tipo.Referencia: https://en.cppreference.com/w/cpp/numeric/constants
fuente
constexpr
desafortunadamente, por eso digo "Definirlo con una función trigonométrica es un dolor"double
(o algún número ridículo si le importan los dobles hipotéticos realmente largos y largos).fsin
instrucción de "aproximadamente 1,37 quintillones de unidades en último lugar, dejando menos de cuatro bits correctos" , y es peor aún para entradas grandes donde la reducción de rango se ajusta varias veces. Esto es algo tangencial a las constantes utilizadaslong double
en C ++, pero de todos modos es ordenado.Como otros dijeron, no existe,
std::pi
pero si desea unPI
valor preciso , puede usar:Esto supone que su implementación de C ++ produce un valor de PI correctamente redondeado
acos(-1.0)
, que es común pero no está garantizado .No lo es
constexpr
, pero en la práctica, los compiladores optimizadores como gcc y clang lo evalúan en tiempo de compilación. Sin embargo, declarar queconst
es importante para el optimizador hacer un buen trabajo.fuente
acos()
función tiene una pendiente infinita enx = -1
. En consecuencia, este método se basa en laacos()
implementación para captar básicamente el caso de un-1
argumento preciso y devolver la constante correcta directamente. Mejor usar algo como lo4*atan(1)
que es matemáticamente mucho más robusto (la pendiente de buen comportamiento enx = 1
y la multiplicación por 4 siempre es precisa con las matemáticas de coma flotante).std::acos
en una expresión constante. clang informa esto como un error. Tenga en cuenta que esta es una extensión no conforme y que eventualmente debería corregirse en gcc. Favor de referirse a esta respuesta para más detalles.Hasta C ++ 20, no, ninguno de los estándares introduce la constante que representaría el número pi (π). Puede aproximar el número en su código:
Otros lenguajes como C # tienen la constante declarada en sus bibliotecas.
Actualización: a partir de C ++ 20, de hecho, hay una
pi
constante declarada dentro del<numbers>
encabezado. Se accede a través:std::numbers::pi
.fuente
inline
para C ++ 17 +.double
. C # lo tiene fácil ya que eldouble
tipo es fijo. Si estuviera en el comité de estándares de C ++, propondría algo comostd::constants<double>::pi
std::numeric_limits<double>::is_iec559;
en ese caso deberías hacer una afirmación estática . Lo cual, lo confieso, es lo que tengo en mi "encabezado maestro". Tenga en cuenta que formalmente debe verificar todos los tipos de punto flotante por separado. El hecho de que uno sea IEEE754 no significa que todos lo sean.M_PI
se define por "un estándar", si no es un estándar de idioma : POSIX con la extensión X / Open System Interfaces (que es muy comúnmente compatible y requerido para la marca oficial de UNIX).(Todavía) no está seguro de lo que habrá en C ++ 20, pero como usted preguntó: probablemente tendrá tales constantes . El documento se fusionó en la última ronda de características de C ++ 20 (para el Borrador del Comité en agosto de 2019).
Específicamente, habrá ambos
std::numbers::pi
(de tipodouble
) y una plantilla variable que puede usar si desea un tipo de punto flotante diferente, por ejemplostd::numbers::pi_v<float>
. La lista completa de constantes se puede ver en [numbers.syn] .fuente
Obviamente no es una buena idea porque no hay un tipo obvio con el que definir pi que sea universalmente aplicable en todos los dominios.
Pi es, por supuesto, un número irracional, por lo que no puede ser representado correctamente por ningún tipo de C ++. Podría argumentar que el enfoque natural, por lo tanto, es definirlo en el tipo de punto flotante más grande disponible. Sin embargo, el tamaño del tipo de coma flotante estándar más grande
long double
no está definido por el estándar C ++, por lo que el valor de la constante variaría entre los sistemas. Peor aún, para cualquier programa en el que el tipo de trabajo no fuera el más grande, la definición de pi sería inapropiada ya que impondría un costo de rendimiento en cada uso de pi.También es trivial para cualquier programador encontrar el valor de pi y definir su propia constante adecuada para su uso, por lo que no ofrece ninguna gran ventaja incluirlo en los encabezados matemáticos.
fuente
pi
una constante polimórfica es el camino claro hacia adelante, en un lenguaje con inferencia de tipo Hindley-Milner. En Haskell, siempre hemos tenidopi :: Floating a => a
, por lo quepi
automáticamente tendría el valor3.1415927
en unFloat
contexto,3.141592653589793
en unDouble
contexto yπ
en un contexto de cálculo simbólico. ¿Pero a la gente realmente le gustaría tener que crear una instancia explícita del parámetro de plantilla? Parece un poco incómodo, especialmente si unalong double
implementación fija daría resultados idénticos en la mayoría de las aplicaciones.auto a = pi<float>;
está completamente bien, sin duda es más legible que notorio4*atan(1)
Editado: para eliminar el término necesario, porque resultó controvertido. Es demasiado de un término absoluto.
C ++ es un lenguaje grande y complejo, por eso el Comité de Estándares solo incluye cosas que son muy necesarias . En la medida de lo posible, se deja a las bibliotecas estándar sin lenguaje ... como Boost.
boost :: matemáticas :: constantes
fuente
std::hermite
ystd::cyl_bessel_i
ystd::cosh
ystd::mersenne_twister_engine
ystd::ranlux48
ystd::cauchy_distribution
ystd::assoc_laguerre
ystd::beta
todos eran absolutamente necesarios, ¡todos los usamos todos los días!