Como usar a constante de PI em C++

quero usar a constante PI e as funções trigonométricas em algum programa C++. Eu tenho as funções trigonométricas com {[[0]}. No entanto, não parece haver uma definição para PI neste arquivo header.

Como posso obter o PI sem o definir manualmente?

Author: Yu Hao, 2009-11-13

17 answers

Em algumas plataformas (especialmente mais antigas) (ver os comentários abaixo) poderá ter de

#define _USE_MATH_DEFINES

E depois incluir o ficheiro de cabeçalho necessário:

#include <math.h>

E o valor de pi pode ser acedido através de:

M_PI

No meu math.h (2014) é definido como:

# define M_PI           3.14159265358979323846  /* pi */

Mas verifique o seu math.h para mais. Um extracto do " old " math.h (em 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.
 */

No entanto:

  1. Em plataformas mais recentes (pelo menos no meu Ubuntu 14.04 de 64 bits) eu não preciso definir o _USE_MATH_DEFINES

  2. Em plataformas Linux (recentes) existem também valores long double fornecidos como uma extensão GNU:

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */
    
 435
Author: fritzone, 2014-04-25 06:54:21

O Pi pode ser calculado como atan(1)*4. Você poderia calcular o valor desta maneira e guardá-lo.

 151
Author: Konamiman, 2009-11-13 08:26:27

Também pode usar o boost, que define constantes matemáticas importantes com a máxima precisão para o tipo requerido (isto é, float vs double).

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

Verifique a documentaçãopara mais exemplos.

 102
Author: BuschnicK, 2009-11-13 12:33:29
Em vez disso, vai buscar à unidade FPU no chip.
double get_PI()
{
    double pi;
    __asm
    {
        fldpi
        fstp pi
    }
    return pi;
}

double PI = get_PI();
 53
Author: Henrik, 2015-06-04 15:01:45
Recomendo que digite em pi com a precisão que precisa. Isso iria adicionar nenhum tempo de cálculo para a sua execução, e seria portátil sem usar qualquer headers ou #define. Calcular acos ou atan é sempre mais caro do que usar um valor pré-calculado.
const double PI  =3.141592653589793238463;
const float  PI_F=3.14159265358979f;
 48
Author: Alex, 2014-01-19 05:40:48

Em vez de escrever

#define _USE_MATH_DEFINES

Eu recomendaria a utilização de -D_USE_MATH_DEFINES ou /D_USE_MATH_DEFINES dependendo do seu compilador.

Desta forma, ter-lhe-á a certeza de que, mesmo no caso de alguém incluir o cabeçalho antes de o fazer (e sem a definição#), ainda terá as constantes em vez de um erro obscuro do compilador que levará uma eternidade a localizar.

 38
Author: Matthieu M., 2009-11-13 12:09:42
Uma vez que a biblioteca padrão oficial não define um IP constante, teria de ser você a defini-lo. Então a resposta à sua pergunta " Como posso obter PI sem defini-lo manualmente?"is" You don'T -- or you rely on some compiler-specific extensions.". Se você não está preocupado com a portabilidade, você poderia verificar o manual do seu compilador para isso.

O C++ permite-lhe escrever

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

Mas a inicialização desta constante não é garantida para ser estática. O compilador G++ however handles those math functions as intrinsics and is able to compute this constant expression at compile-time.

 36
Author: sellibitze, 2009-11-13 08:37:38

Da página de matemática do Posix man.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, 2013-06-14 21:26:49

O Padrão C++ não tem uma constante para PI.

Muitos compiladores de c++ definem M_PI em cmath (ou em math.h para C) como uma extensão não-padrão. Você pode ter que #define _USE_MATH_DEFINES antes que você possa vê-lo.

 24
Author: RichieHindle, 2009-11-13 08:27:24

Eu faria

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

Ou

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

Eu não faria escrever em π Com a precisão necessária. O que é que isso quer dizer? A precisão de que você precisa é a precisão de T, mas não sabemos nada sobre T.

Podes dizer: do que estás a falar? T será float, double ou long double. Então, basta digitar a precisão de long double, i.e.
template<typename T>
T const pi = static_cast<T>(/* long double precision π */);
Mas sabes mesmo que não haverá uma nova tipo de vírgula flutuante na norma no futuro com uma precisão ainda maior do que long double? Tu não. E é por isso que a primeira solução é bela. Você pode ter certeza de que o padrão sobrecarregaria as funções trigonométricas para um novo tipo. E, por favor, não diga que a avaliação de uma função trigonométrica na inicialização é uma penalidade de desempenho.
 11
Author: 0xbadf00d, 2016-03-14 14:23:22
{[[2]}eu geralmente prefiro definir o meu próprio: {[[0]} porque nem todas as implementações o fornecem para você.

A questão de saber se esta função é chamada no tempo de execução ou se é estática no tempo de compilação não é normalmente uma questão, porque só acontece uma vez de qualquer maneira.

 8
Author: Sumudu Fernando, 2009-11-18 04:03:41

Uso o seguinte num dos meus cabeçalhos comuns no projecto que cobre todas as 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

Numa nota lateral, todos os compiladores abaixo definem constantes M_PI e M_PIl se incluir <cmath>. Não há necessidade de adicionar ' # definir _USE_MATH_DEFINES que só é necessário para VC++.

x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+
 7
Author: ShitalShah, 2017-02-13 15:16:58

Acabei de encontrar este artigo por Danny Kalev que tem uma grande dica para C++14 e up.

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

Eu pensei que isso era muito legal( embora eu iria usar o PI de maior precisão que eu poderia), especialmente porque os modelos podem usá-lo com base no 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, 2018-01-27 01:50:09

No windows (cygwin + g++), achei necessário adicionar a bandeira {[[0]} para o pré-processador processar a definição de M_PI em math.h.

 2
Author: Papa Smurf, 2014-12-15 12:36:44

O C++14 permite-lhe fazer static constexpr auto pi = acos(-1);

 2
Author: Willy Goat, 2016-03-21 20:09:45

Podes fazer isto:

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

Se M_PI já estiver definido em cmath, isto não fará mais nada do que incluir cmath. Se M_PI não está definido (o que é o caso, por exemplo, no Visual Studio), ele irá defini-lo. Em ambos os casos, você pode usar M_PI para obter o valor de pi.

Este valor de pi vem da qmath do Qt Creator.h.

 1
Author: Donald Duck, 2016-11-09 11:53:14

Valores como M_PI, M_PI_2, M_PI_4, etc não são C++ normais, pelo que uma constante parece ser uma solução melhor. Diferentes expressões const podem ser formuladas que calculam o mesmo pi e preocupa-me se elas (todas) me fornecem a precisão completa. A norma C++ não menciona explicitamente como calcular o pi. Portanto, tenho tendência para voltar a definir o pi manualmente. Eu gostaria de compartilhar a solução abaixo que suporta todos os tipos de frações de pi em total precisão.

#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, 2018-07-31 08:49:13