Eu quero usar as funções constantes e trigonométricas do PI em algum programa C ++. Eu recebo as funções trigonométricas com include <math.h>
. No entanto, não parece haver uma definição para PI neste arquivo de cabeçalho.
Como posso obter o PI sem defini-lo manualmente?
c++
trigonometry
Etan
fonte
fonte
3.14
,3.141592
eatan(1) * 4
?Respostas:
Em algumas plataformas (especialmente mais antigas) (veja os comentários abaixo), pode ser necessário
e inclua o arquivo de cabeçalho necessário:
e o valor de pi pode ser acessado via:
No meu
math.h
(2014), é definido como:mas verifique o seu
math.h
para mais. Um extrato do "antigo"math.h
(em 2009):Contudo:
em plataformas mais novas (pelo menos no meu Ubuntu 14.04 de 64 bits), não preciso definir o
_USE_MATH_DEFINES
Nas plataformas Linux (recentes), existem
long double
valores também fornecidos como uma Extensão GNU:fonte
#define _USE_MATH_DEFINES
seguido por#include <math.h>
defineM_PI
no visual c ++. Obrigado.cmath
vez demath.h
._USE_MATH_DEFINES
se o GCC reclama, é porque__STRICT_ANSI__
está definido (talvez você tenha passado-pedantic
ou-std=c++11
) que nãoM_PI
permite ser definido, portanto, o defina-D__STRICT_ANSI__
. Ao definir você mesmo, já que é C ++, em vez de uma macro, você deveconstexpr auto M_PI = 3.14159265358979323846;
.Pi pode ser calculado como
atan(1)*4
. Você pode calcular o valor dessa maneira e armazená-lo em cache.fonte
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
(grosso modo). Eu não apostaria nisso. Seja normal e use um literal bruto para definir a constante. Por que perder precisão quando você não precisa?atan2(0, -1);
.atan
não éconstexpr
.acos(-1)
vez disso, não há necessidadeatan2
.Você também pode usar o boost, que define constantes matemáticas importantes com a máxima precisão para o tipo solicitado (por exemplo, float vs double).
Confira a documentação do impulso para mais exemplos.
fonte
not gonna use libs
-opinion é uma praga e provavelmente a principal razão para um software ruim escrito em C ++.Obtê-lo da unidade FPU no chip:
fonte
Eu recomendaria apenas digitar pi com a precisão que você precisa. Isso não adicionaria tempo de cálculo à sua execução e seria portátil sem o uso de cabeçalhos ou #defines. Calcular acos ou atan é sempre mais caro do que usar um valor pré-calculado.
fonte
const
aconstexpr
.constexpr
.Em vez de escrever
Eu recomendaria usar
-D_USE_MATH_DEFINES
ou/D_USE_MATH_DEFINES
dependendo do seu compilador.Dessa forma, você tem certeza de que, mesmo no caso de alguém incluir o cabeçalho antes de você (e sem o #define), você ainda terá as constantes, em vez de um erro obscuro do compilador, que levará anos para rastrear.
fonte
<cmath>
em locais diferentes, isso será uma grande dor (especialmente se estiver incluído em outra biblioteca que você está incluindo). Teria sido muito melhor se eles colocassem essa parte fora dos protetores de cabeçalho, mas agora não podem fazer muito sobre isso agora. A diretiva do compilador funciona muito bem mesmo.Como a biblioteca padrão oficial não define um PI constante, você precisa defini-lo. Portanto, a resposta para sua pergunta "Como posso obter o PI sem defini-lo manualmente?" é "Você não precisa - ou confia em algumas extensões específicas do compilador.". Se você não está preocupado com a portabilidade, consulte o manual do seu compilador.
C ++ permite escrever
mas não é garantido que a inicialização dessa constante seja estática. No entanto, o compilador G ++ lida com essas funções matemáticas como intrínsecas e é capaz de calcular essa expressão constante em tempo de compilação.
fonte
4*atan(1.)
:atan
é fácil de implementar e multiplicar por 4 é uma operação exata. É claro que os compiladores modernos dobram (visam dobrar) todas as constantes com a precisão necessária, e é perfeitamente razoável usaracos(-1)
ou mesmostd::abs(std::arg(std::complex<double>(-1.,0.)))
qual é o inverso da fórmula de Euler e, portanto, mais esteticamente agradável do que parece (adicioneiabs
porque não lembre-se de como o plano complexo é cortado ou se é definido).Na página do manual Posix de math.h :
fonte
C ++ 20
std::numbers::pi
Finalmente chegou: http://eel.is/c++draft/numbers
Espero que o uso seja como:
Vou tentar quando o suporte chegar ao GCC, o GCC 9.1.0 com
g++-9 -std=c++2a
ainda não o suporta.A proposta aceita descreve:
Há também um
std::numbers::e
claro :-) Como calcular a constante de Euler ou a alimentação de Euler em C ++?Essas constantes usam o recurso de modelo de variável C ++ 14: C ++ 14: Modelos de variável C ++ 14: qual é o seu objetivo? Algum exemplo de uso?
Nas versões anteriores do rascunho, a constante estava em
std::math::pi
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdffonte
O C ++ padrão não tem uma constante para o PI.
Muitos compiladores C ++ definem
M_PI
incmath
(ou inmath.h
for C) como uma extensão não padrão. Você pode precisar fazer isso#define _USE_MATH_DEFINES
antes de poder vê-lo.fonte
eu faria
ou
Eu não digitaria π com a precisão que você precisa . O que isso quer dizer? A precisão de que você precisa é a precisão
T
, mas não sabemos nada sobreT
.Você pode dizer: Do que você está falando?
T
seráfloat
,double
oulong double
. Então, basta digitar a precisão delong double
, ieMas você realmente sabe que no futuro não haverá um novo tipo de ponto flutuante com uma precisão ainda mais alta do que
long double
? Você nãoE é por isso que a primeira solução é linda. 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.
fonte
arg(log(x)) == π
para todos0 < x < 1
.Eu uso o seguinte em um dos meus cabeçalhos comuns no projeto que abrange todas as bases:
Em uma nota lateral, todos os compiladores abaixo definem constantes M_PI e M_PIl se você incluir
<cmath>
. Não há necessidade de adicionar `#define _USE_MATH_DEFINES, que é necessário apenas para o VC ++.fonte
M_PI
sem a necessidade de_USE_MATH_DEFINES
Geralmente, prefiro definir o meu:
const double PI = 2*acos(0.0);
porque nem todas as implementações fornecem isso para você.A questão de saber se essa função é chamada em tempo de execução ou estática em tempo de compilação geralmente não é um problema, porque só acontece uma vez.
fonte
double x = pi * 1.5;
etc.). Se você pretende usar o PI em matemática crocante em loops apertados, é melhor garantir que o valor seja conhecido pelo compilador.Acabei de encontrar este artigo de Danny Kalev, que tem uma ótima dica para C ++ 14 e superior.
Achei isso muito legal (embora eu usasse o PI de maior precisão possível), principalmente porque os modelos podem usá-lo com base no tipo.
fonte
Valores como M_PI, M_PI_2, M_PI_4, etc não são C ++ padrão, portanto, um constexpr parece uma solução melhor. Diferentes expressões const podem ser formuladas para calcular o mesmo pi e me preocupa se elas (todas) me fornecem a precisão total. O padrão C ++ não menciona explicitamente como calcular pi. Portanto, eu tendem a voltar a definir pi manualmente. Gostaria de compartilhar a solução abaixo, que suporta todos os tipos de frações de pi com total precisão.
fonte
No windows (cygwin + g ++), achei necessário adicionar a flag
-D_XOPEN_SOURCE=500
para o pré-processador processar a definição deM_PI
inmath.h
.fonte
M_PI
trabalhar em uma plataforma específica. Isso não é um comentário em uma resposta para outra plataforma, assim como uma resposta para outra plataforma é um comentário sobre essa.C ++ 14 permite que você faça
static constexpr auto pi = acos(-1);
fonte
std::acos
não é umconstexpr
. Portanto, seu código não será compilado.acos
não éconstexpr
em C ++ 14, e não é proposta para tornar-seconstexpr
mesmo em C ++ 17constexpr
? Aparentemente não: stackoverflow.com/questions/17347935/constexpr-math-functionsconstexpr
, veja, por exemplo ( github.com/kthohr/gcem ). Mas eles não são compatíveis com as funções C de mesmo nome, portanto não podem assumir o controle dos nomes antigos.Algumas soluções elegantes. Duvido que a precisão das funções trigonométricas seja igual à precisão dos tipos. Para aqueles que preferem escrever um valor constante, isso funciona para g ++: -
A precisão de 256 dígitos decimais deve ser suficiente para qualquer tipo futuro longo, longo e longo. Se mais forem necessárias, visite https://www.piday.org/million/ .
fonte
fonte
Você consegue fazer isso:
Se
M_PI
já estiver definidocmath
, isso não fará nada além de incluircmath
. SeM_PI
não estiver definido (como é o caso, por exemplo, no Visual Studio), ele será definido. Nos dois casos, você pode usarM_PI
para obter o valor de pi.Esse valor de pi vem do qmath.h do Qt Creator.
fonte
Você pode usar isso:
As constantes matemáticas não são definidas no padrão C / C ++. Para usá-los, você deve primeiro definir
_USE_MATH_DEFINES
e incluircmath
oumath.h
.fonte