Ich möchte die PI-Konstante und die trigonometrischen Funktionen in einigen C ++ - Programmen verwenden. Ich bekomme die trigonometrischen Funktionen mit include <math.h>
. Es scheint jedoch keine Definition für PI in dieser Header-Datei zu geben.
Wie kann ich PI erhalten, ohne es manuell zu definieren?
c++
trigonometry
Etan
quelle
quelle
3.14
,3.141592
undatan(1) * 4
?Antworten:
Auf einigen (insbesondere älteren) Plattformen (siehe Kommentare unten) müssen Sie dies möglicherweise tun
und fügen Sie dann die erforderliche Header-Datei hinzu:
und auf den Wert von pi kann zugegriffen werden über:
In meinem
math.h
(2014) ist es definiert als:aber überprüfen Sie Ihre
math.h
für mehr. Ein Auszug aus dem "Alten"math.h
(2009):Jedoch:
Auf neueren Plattformen (zumindest auf meinem 64-Bit-Ubuntu 14.04) muss ich das nicht definieren
_USE_MATH_DEFINES
Auf (neueren) Linux-Plattformen werden auch
long double
Werte als GNU-Erweiterung bereitgestellt:quelle
#define _USE_MATH_DEFINES
gefolgt von#include <math.h>
DefinitionenM_PI
in Visual C ++. Vielen Dank.cmath
anstelle von einschließenmath.h
._USE_MATH_DEFINES
ob sich GCC beschwert, liegt dies daran, dass__STRICT_ANSI__
definiert ist (vielleicht haben Sie bestanden-pedantic
oder-std=c++11
), was nichtM_PI
definiert werden kann, und daher die Definition mit aufhebt-D__STRICT_ANSI__
. Wenn Sie es selbst definieren, sollten Sie anstelle eines Makros C ++ verwendenconstexpr auto M_PI = 3.14159265358979323846;
.Pi kann berechnet werden als
atan(1)*4
. Sie können den Wert auf diese Weise berechnen und zwischenspeichern.quelle
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
(grob gesagt). Ich würde nicht darauf wetten. Seien Sie normal und verwenden Sie ein Rohliteral, um die Konstante zu definieren. Warum Präzision verlieren, wenn Sie nicht müssen?atan2(0, -1);
.atan
ist nichtconstexpr
.acos(-1)
stattdessen, keine Notwendigkeit füratan2
.Sie können auch Boost verwenden, das wichtige mathematische Konstanten mit maximaler Genauigkeit für den angeforderten Typ definiert (dh float vs double).
Weitere Beispiele finden Sie in der Boost-Dokumentation .
quelle
not gonna use libs
Meinung ein Schädling und wahrscheinlich der Hauptgrund für schlechte Software, die in C ++ geschrieben wurde.Holen Sie es sich stattdessen von der FPU-Einheit auf dem Chip:
quelle
Ich würde empfehlen, nur pi mit der Genauigkeit einzugeben, die Sie benötigen. Dies würde Ihrer Ausführung keine Berechnungszeit hinzufügen und wäre portabel, ohne Header oder #defines zu verwenden. Die Berechnung von Acos oder Atan ist immer teurer als die Verwendung eines vorberechneten Wertes.
quelle
const
aconstexpr
.constexpr
.Anstatt zu schreiben
Ich würde empfehlen,
-D_USE_MATH_DEFINES
oder/D_USE_MATH_DEFINES
abhängig von Ihrem Compiler.Auf diese Weise können Sie sicher sein, dass Sie selbst im Falle einer Person, die den Header vor Ihnen enthält (und ohne #define), die Konstanten anstelle eines obskuren Compilerfehlers haben, dessen Aufspüren Sie ewig brauchen werden.
quelle
<cmath>
an verschiedenen Orten verwenden, wird dies zu einem großen Problem (insbesondere wenn es in einer anderen Bibliothek enthalten ist, die Sie einschließen). Es wäre viel besser gewesen, wenn sie diesen Teil außerhalb der Kopfschutzvorrichtungen platziert hätten, aber jetzt können sie nicht viel dagegen tun. Die Compiler-Direktive funktioniert in der Tat ziemlich gut.Da die offizielle Standardbibliothek keinen konstanten PI definiert, müssten Sie ihn selbst definieren. Die Antwort auf Ihre Frage "Wie kann ich PI erhalten, ohne es manuell zu definieren?" lautet "Sie tun es nicht - oder Sie verlassen sich auf einige compilerspezifische Erweiterungen." Wenn Sie sich keine Gedanken über die Portabilität machen, können Sie dies im Handbuch Ihres Compilers nachlesen.
Mit C ++ können Sie schreiben
Es ist jedoch nicht garantiert, dass die Initialisierung dieser Konstante statisch ist. Der G ++ - Compiler behandelt diese mathematischen Funktionen jedoch als intrinsisch und kann diesen konstanten Ausdruck zur Kompilierungszeit berechnen.
quelle
4*atan(1.)
:atan
ist einfach zu implementieren und das Multiplizieren mit 4 ist eine exakte Operation. Natürlich falten moderne Compiler alle Konstanten mit der erforderlichen Präzision (zielen darauf ab, sie zu falten), und es ist durchaus sinnvoll, sie zu verwenden,acos(-1)
oder sogarstd::abs(std::arg(std::complex<double>(-1.,0.)))
das Gegenteil von Eulers Formel und damit ästhetischer, als es scheint (ich habe hinzugefügt,abs
weil ich es nicht tue). Ich erinnere mich nicht, wie die komplexe Ebene geschnitten wird oder ob dies überhaupt definiert ist.Aus der Posix-Manpage von math.h :
quelle
C ++ 20
std::numbers::pi
Endlich ist es soweit: http://eel.is/c++draft/numbers
Ich erwarte, dass die Verwendung wie folgt ist:
Ich werde es versuchen, wenn der Support bei GCC eintrifft. GCC 9.1.0
g++-9 -std=c++2a
unterstützt ihn immer noch nicht.Der akzeptierte Vorschlag beschreibt:
Es gibt
std::numbers::e
natürlich auch eine :-) Wie berechnet man die Eulerkonstante oder Euler in C ++?Diese Konstanten verwenden die C ++ 14-Variablenvorlagenfunktion: C ++ 14-Variablenvorlagen: Wozu dienen sie? Irgendein Verwendungsbeispiel?
In früheren Versionen des Entwurfs befand sich die Konstante unter
std::math::pi
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdfquelle
Standard C ++ hat keine Konstante für PI.
Viele C ++ - Compiler definieren
M_PI
incmath
(oder inmath.h
für C) eine nicht standardmäßige Erweiterung. Möglicherweise müssen Sie,#define _USE_MATH_DEFINES
bevor Sie es sehen können.quelle
Ich würde es tun
oder
Ich würde nicht auf die Genauigkeit in π eingeben Sie benötigen . Was soll das überhaupt bedeuten? Die Präzision, die Sie benötigen, ist die Präzision von
T
, aber wir wissen nichts darüberT
.Sie könnten sagen: Worüber reden Sie?
T
wird seinfloat
,double
oderlong double
. Geben Sie also einfach die Genauigkeit von einlong double
, zAber wissen Sie wirklich, dass es in Zukunft keinen neuen Gleitkommatyp im Standard geben wird, der noch präziser ist als
long double
? Das tust du nicht.Und deshalb ist die erste Lösung schön. Sie können ziemlich sicher sein, dass der Standard die trigonometrischen Funktionen für einen neuen Typ überladen würde.
Und bitte sagen Sie nicht, dass die Auswertung einer trigonometrischen Funktion bei der Initialisierung eine Leistungsbeeinträchtigung darstellt.
quelle
arg(log(x)) == π
für alle0 < x < 1
.Ich verwende Folgendes in einem meiner gemeinsamen Header im Projekt, das alle Grundlagen abdeckt:
Nebenbei bemerkt definieren alle unten aufgeführten Compiler die Konstanten M_PI und M_PIl, wenn Sie sie einschließen
<cmath>
. Es ist nicht erforderlich, `#define _USE_MATH_DEFINES hinzuzufügen, was nur für VC ++ erforderlich ist.quelle
M_PI
ohne Notwendigkeit_USE_MATH_DEFINES
Im Allgemeinen definiere ich lieber meine eigenen:
const double PI = 2*acos(0.0);
weil nicht alle Implementierungen sie für Sie bereitstellen.Die Frage, ob diese Funktion zur Laufzeit aufgerufen oder zur Kompilierungszeit statisch ausgegeben wird, ist normalerweise kein Problem, da sie ohnehin nur einmal auftritt.
quelle
double x = pi * 1.5;
und dergleichen). Wenn Sie jemals beabsichtigen, PI in knackigen Berechnungen in engen Schleifen zu verwenden, sollten Sie sicherstellen, dass der Wert dem Compiler bekannt ist.Ich bin gerade auf diesen Artikel von Danny Kalev gestoßen, der einen großartigen Tipp für C ++ 14 und höher enthält.
Ich fand das ziemlich cool (obwohl ich dort den PI mit der höchsten Präzision verwenden würde), vor allem, weil Vorlagen ihn basierend auf dem Typ verwenden können.
quelle
Werte wie M_PI, M_PI_2, M_PI_4 usw. sind kein Standard-C ++, daher scheint ein constexpr eine bessere Lösung zu sein. Es können verschiedene const-Ausdrücke formuliert werden, die den gleichen pi berechnen, und es geht mich an, ob sie (alle) mir die volle Genauigkeit bieten. Der C ++ - Standard erwähnt nicht explizit, wie pi berechnet wird. Daher neige ich dazu, pi manuell zu definieren. Ich möchte die folgende Lösung teilen, die alle Arten von Brüchen von pi mit voller Genauigkeit unterstützt.
quelle
Unter Windows (cygwin + g ++) musste das Flag
-D_XOPEN_SOURCE=500
für den Präprozessor hinzugefügt werden , um die Definition vonM_PI
in zu verarbeitenmath.h
.quelle
M_PI
auf einer bestimmten Plattform zu arbeiten. Das ist kein Kommentar zu einer Antwort für eine andere Plattform mehr, sondern eine Antwort für eine andere Plattform ist ein Kommentar zu dieser.Mit C ++ 14 können Sie dies tun
static constexpr auto pi = acos(-1);
quelle
std::acos
ist nicht einconstexpr
. Ihr Code wird also nicht kompiliert.acos
es nichtconstexpr
in C ++ 14 ist und nicht vorgeschlagen wird,constexpr
auch in C ++ 17 zu werdenconstexpr
? Anscheinend nicht: stackoverflow.com/questions/17347935/constexpr-math-functionsconstexpr
, siehe zum Beispiel ( github.com/kthohr/gcem ). Sie sind jedoch nicht abwärtskompatibel mit den gleichnamigen C-Funktionen, sodass sie die alten Namen nicht übernehmen können.Einige elegante Lösungen. Ich bin mir nicht sicher, ob die Genauigkeit der trigonometrischen Funktionen der Genauigkeit der Typen entspricht. Für diejenigen, die lieber einen konstanten Wert schreiben, funktioniert dies für g ++: -
Die Genauigkeit von 256 Dezimalstellen sollte für jeden zukünftigen Long Long Long Double-Typ ausreichen. Wenn weitere erforderlich sind, besuchen Sie https://www.piday.org/million/ .
quelle
quelle
Du kannst das:
Wenn dies
M_PI
bereits in definiert istcmath
, wird nichts anderes als Include ausgeführtcmath
. WennM_PI
es nicht definiert ist (was beispielsweise in Visual Studio der Fall ist), wird es definiert. In beiden Fällen können Sie verwendenM_PI
den Wert von pi abrufen.Dieser Wert von pi stammt aus Qmath.h von Qt Creator.
quelle
Sie können das verwenden:
Mathematische Konstanten sind in Standard C / C ++ nicht definiert. Um sie zu verwenden, müssen Sie zuerst definieren
_USE_MATH_DEFINES
und dann schließencmath
odermath.h
.quelle