Chcę użyć funkcji PI i funkcji trygonometrycznych w niektórych programach C ++. Dostaję funkcje trygonometryczne z include <math.h>
. Wydaje się jednak, że w tym pliku nagłówkowym nie ma definicji PI.
Jak mogę uzyskać PI bez ręcznego definiowania?
c++
trigonometry
Etan
źródło
źródło
3.14
,3.141592
aatan(1) * 4
?Odpowiedzi:
Na niektórych (szczególnie starszych) platformach (patrz komentarze poniżej) może być konieczne
a następnie dołącz niezbędny plik nagłówka:
a wartość pi można uzyskać poprzez:
W moim
math.h
(2014) jest to zdefiniowane jako:ale sprawdź
math.h
więcej. Fragment „starego”math.h
(w 2009 r.):Jednak:
na nowszych platformach (przynajmniej na moim 64-bitowym Ubuntu 14.04) nie muszę definiować
_USE_MATH_DEFINES
Na (najnowszych) platformach Linux są
long double
też wartości dostarczane jako rozszerzenie GNU:źródło
#define _USE_MATH_DEFINES
a następnie#include <math.h>
definicjeM_PI
w Visual C ++. Dzięki.cmath
zamiastmath.h
._USE_MATH_DEFINES
czy GCC narzeka, że to dlatego, że__STRICT_ANSI__
jest zdefiniowane (być może zdałeś-pedantic
lub-std=c++11
zdałeś), co nie pozwalaM_PI
na zdefiniowanie, dlatego nie zdefiniuj go-D__STRICT_ANSI__
. Definiując go sam, ponieważ jest to C ++, zamiast makra powinieneśconstexpr auto M_PI = 3.14159265358979323846;
.Pi można obliczyć jako
atan(1)*4
. Możesz w ten sposób obliczyć wartość i zapisać ją w pamięci podręcznej.źródło
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
(z grubsza). Nie postawiłbym na to. Bądź normalny i użyj surowego literału, aby zdefiniować stałą. Po co tracić precyzję, kiedy nie jest to konieczne?atan2(0, -1);
.atan
nie jestconstexpr
.acos(-1)
Zamiast tego spróbujatan2
.Możesz także użyć wzmocnienia, które definiuje ważne stałe matematyczne z maksymalną dokładnością dla żądanego typu (tj. Zmiennoprzecinkowe vs podwójne).
Sprawdź dokumentację doładowania, aby uzyskać więcej przykładów.
źródło
not gonna use libs
opinia jest szkodnikiem i prawdopodobnie głównym powodem złego oprogramowania napisanego w C ++.Zamiast tego pobierz go z jednostki FPU na chipie:
źródło
Polecam po prostu wpisać pi z dokładnością, jakiej potrzebujesz. To nie zwiększy czasu wykonywania obliczeń i będzie przenośne bez użycia nagłówków lub # definicji. Obliczanie acos lub atan jest zawsze droższe niż stosowanie wstępnie obliczonej wartości.
źródło
const
aconstexpr
.constexpr
.Zamiast pisać
Polecam używanie
-D_USE_MATH_DEFINES
lub/D_USE_MATH_DEFINES
zależnie od twojego kompilatora.W ten sposób masz pewność, że nawet w przypadku, gdy ktoś włączy nagłówek, zanim to zrobisz (i bez #define) nadal będziesz mieć stałe zamiast niejasnego błędu kompilatora, którego wyśledzenie zajmie Ci całe wieki.
źródło
<cmath>
w różnych miejscach, staje się to dużym problemem (szczególnie jeśli jest dołączony przez inną bibliotekę, którą dołączasz). Byłoby znacznie lepiej, gdyby umieścili tę część poza osłonami hedera, ale cóż, teraz niewiele można na to poradzić. Dyrektywa kompilatora działa naprawdę całkiem dobrze.Ponieważ oficjalna biblioteka standardowa nie definiuje stałego PI, musiałbyś go zdefiniować sam. Więc odpowiedź na twoje pytanie „Jak mogę uzyskać PI bez definiowania go ręcznie?” to „Nie - lub polegasz na niektórych rozszerzeniach specyficznych dla kompilatora”. Jeśli nie martwisz się o przenośność, możesz to sprawdzić w instrukcji kompilatora.
C ++ pozwala pisać
ale nie można zagwarantować, że inicjalizacja tej stałej będzie statyczna. Kompilator G ++ obsługuje jednak te funkcje matematyczne jako elementy wewnętrzne i jest w stanie obliczyć to stałe wyrażenie w czasie kompilacji.
źródło
4*atan(1.)
:atan
jest łatwy do wdrożenia, a pomnożenie przez 4 jest dokładną operacją. Oczywiście współczesne kompilatory składają (dążą do złożenia) wszystkie stałe z wymaganą precyzją i jest całkowicie rozsądne w użyciu,acos(-1)
a nawetstd::abs(std::arg(std::complex<double>(-1.,0.)))
odwrotne do formuły Eulera, a zatem bardziej estetyczne niż się wydaje (dodałem,abs
ponieważ nie „ pamiętaj, w jaki sposób wycina się płaszczyznę złożoną lub jeśli jest to w ogóle zdefiniowane).Ze strony podręcznika Posix math.h :
źródło
C ++ 20
std::numbers::pi
W końcu dotarł: http://eel.is/c++draft/numbers
Oczekuję, że użycie będzie takie jak:
Spróbuję, kiedy wsparcie dotrze do GCC, GCC 9.1.0 z
g++-9 -std=c++2a
nadal go nie obsługuje.Przyjęta propozycja opisuje:
Jest też
std::numbers::e
oczywiście :-) Jak obliczyć stałą Eulera lub Eulera zasilanego w C ++?Te stałe używają funkcji szablonu zmiennej C ++ 14: Szablony zmiennych C ++ 14: jaki jest ich cel? Dowolny przykład użycia?
We wcześniejszych wersjach projektu stała była pod
std::math::pi
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdfźródło
Standardowy C ++ nie ma stałej dla PI.
Wiele kompilatorów C ++ definiuje
M_PI
wcmath
(lubmath.h
dla C) jako niestandardowe rozszerzenie. Być może będziesz musiał#define _USE_MATH_DEFINES
to zobaczyć.źródło
chciałbym zrobić
lub
Chciałbym nie wpisując Õ do precyzji trzeba . Co to w ogóle ma znaczyć? Precyzja potrzebne jest precyzja
T
, ale nic o tym wiedziećT
.Możesz powiedzieć: o czym ty mówisz?
T
będziefloat
,double
albolong double
. Więc po prostu wpisz dokładnośćlong double
, tjAle czy naprawdę wiesz, że w przyszłości nie będzie nowego typu zmiennoprzecinkowego z jeszcze większą precyzją niż
long double
? Ty nie.I dlatego pierwsze rozwiązanie jest piękne. Możesz być całkiem pewien, że standard przeciąża funkcje trygonometryczne dla nowego typu.
I proszę, nie mów, że ocena funkcji trygonometrycznych przy inicjalizacji jest ograniczeniem wydajności.
źródło
arg(log(x)) == π
dla wszystkich0 < x < 1
.Używam następujących w jednym z moich wspólnych nagłówków w projekcie, który obejmuje wszystkie podstawy:
Na marginesie, wszystkie poniższe kompilatory definiują stałe M_PI i M_PIl, jeśli je uwzględnisz
<cmath>
. Nie ma potrzeby dodawania `#define _USE_MATH_DEFINES, który jest wymagany tylko w VC ++.źródło
M_PI
bez potrzeby_USE_MATH_DEFINES
Generalnie wolę zdefiniować własne:
const double PI = 2*acos(0.0);
ponieważ nie wszystkie implementacje to zapewniają.Pytanie, czy funkcja ta jest wywoływana w czasie wykonywania, czy jest statycznie wyłączana w czasie kompilacji, zwykle nie stanowi problemu, ponieważ dzieje się tak tylko raz.
źródło
double x = pi * 1.5;
i tym podobne). Jeśli kiedykolwiek zamierzasz używać PI w chrupiącej matematyce w ciasnych pętlach, lepiej upewnij się, że wartość jest znana kompilatorowi.Właśnie natknąłem tego artykułu przez Danny Kalev który ma wielką wskazówka dla C ++ 14 i do góry.
Pomyślałem, że to całkiem fajne (chociaż użyłbym tam najwyższej precyzji PI tam, gdzie mogłem), zwłaszcza, że szablony mogą używać tego na podstawie typu.
źródło
Wartości takie jak M_PI, M_PI_2, M_PI_4 itp. Nie są standardowym C ++, więc constexpr wydaje się lepszym rozwiązaniem. Można sformułować różne wyrażenia stałych, które obliczają to samo pi i dotyczy mnie to, czy (wszystkie) zapewniają mi pełną dokładność. Standard C ++ nie mówi wprost o tym, jak obliczyć pi. Dlatego zwykle wracam do ręcznego definiowania pi. Chciałbym podzielić się poniższym rozwiązaniem, które obsługuje wszystkie frakcje pi z pełną dokładnością.
źródło
W systemie Windows (cygwin + g ++) uważam za konieczne dodanie flagi
-D_XOPEN_SOURCE=500
dla preprocesora w celu przetworzenia definicjiM_PI
wmath.h
.źródło
M_PI
rozpoczęcia pracy na konkretnej platformie. To już nie jest komentarz do odpowiedzi na jakąś inną platformę, ale odpowiedź na jakąś inną platformę jest komentarzem do tej.C ++ 14 pozwala na to
static constexpr auto pi = acos(-1);
źródło
std::acos
nie jestconstexpr
. Twój kod się nie skompiluje.acos
nie ma goconstexpr
w C ++ 14 i nie proponuje się, aby stał sięconstexpr
nawet w C ++ 17constexpr
? Najwyraźniej nie: stackoverflow.com/questions/17347935/constexpr-math-functionsconstexpr
, patrz na przykład ( github.com/kthohr/gcem ). Ale nie są one kompatybilne wstecz z funkcjami C o tej samej nazwie, więc nie mogą przejąć starych nazw.Kilka eleganckich rozwiązań. Wątpię jednak, aby precyzja funkcji trygonometrycznych była równa precyzji typów. Dla tych, którzy wolą zapisywać stałą wartość, działa to dla g ++: -
Dokładność 256 cyfr dziesiętnych powinna wystarczyć dla każdego przyszłego długiego, długiego, podwójnego typu. Jeśli potrzebujesz więcej, odwiedź https://www.piday.org/million/ .
źródło
źródło
Możesz to zrobić:
Jeśli
M_PI
jest już zdefiniowane wcmath
, nie zrobi nic innego niż dołączyćcmath
. JeśliM_PI
nie jest zdefiniowany (co ma miejsce na przykład w Visual Studio), to go zdefiniuje. W obu przypadkach możesz użyćM_PI
aby uzyskać wartość pi.Ta wartość pi pochodzi z qmath.h Qt Creatora.
źródło
Możesz użyć tego:
Stałe matematyczne nie są zdefiniowane w standardzie C / C ++. Aby ich użyć, musisz najpierw zdefiniować,
_USE_MATH_DEFINES
a następnie dołączyćcmath
lubmath.h
.źródło