643 Stimmen

Verwendung der PI-Konstante in C++

Ich möchte die PI-Konstante und trigonometrische Funktionen in einem C++-Programm verwenden. Ich erhalte die trigonometrischen Funktionen mit include <math.h> . Allerdings scheint es in dieser Header-Datei keine Definition für PI zu geben.

Wie kann ich PI bekommen, ohne es manuell zu definieren?

3 Stimmen

@tiwo, wollen Sie wissen, was der Unterschied ist zwischen 3.14 , 3.141592 et atan(1) * 4 ?

46 Stimmen

Nebenbei bemerkt: cmath sollte in C++ anstelle von math.h verwendet werden, die für C bestimmt ist.

5 Stimmen

In loser Verbindung: siehe cise.ufl.edu/~manuel/obfuscate/pi.c wie man den Wert von PI direkt aus der Definition berechnet.

57voto

Alex Punkte 609

Ich würde empfehlen, pi einfach in der benötigten Genauigkeit einzugeben. Dies würde keine zusätzliche Rechenzeit für die Ausführung benötigen und wäre ohne Header oder #defines portabel. Die Berechnung von acos oder atan ist immer teurer als die Verwendung eines vorberechneten Wertes.

const double PI  =3.141592653589793238463;
const float  PI_F=3.14159265358979f;

34 Stimmen

Dies ist ein gutes Beispiel dafür, warum wir diesen Ansatz nicht wählen sollten, denn wir Menschen machen Fehler, runden ab, kopieren und fügen ein usw. Ich denke, die Verwendung von M_PI ist der richtige Ansatz.

18 Stimmen

Wenn man dies in C++11 macht, sollte man die const a constexpr .

4 Stimmen

@nacho4d Auch ich bevorzuge M_PI, wenn es verfügbar ist, aber nicht alle Systeme sind POSIX-kompatibel. Ich denke, dieser Ansatz ist besser als die 4*atan(1)-Methode für die Fälle, in denen M_PI nicht verfügbar ist.

52voto

Matthieu M. Punkte 266317

Anstatt zu schreiben

#define _USE_MATH_DEFINES

Ich würde die Verwendung von -D_USE_MATH_DEFINES o /D_USE_MATH_DEFINES abhängig von Ihrem Compiler.

Auf diese Weise können Sie sicher sein, dass Sie selbst dann, wenn jemand den Header vor Ihnen einfügt (und ohne #define), die Konstanten haben und nicht einen obskuren Compilerfehler, den Sie erst nach Ewigkeiten aufspüren können.

0 Stimmen

Guter Tipp. Wenn "Sie" eine Kompiliereinheit sind, können Sie natürlich sicherstellen, dass das Makro definiert ist, bevor etwas eingefügt wird. Aber wenn "Sie" eine Header-Datei sind, liegt es außerhalb Ihrer Kontrolle.

3 Stimmen

Selbst wenn "Sie" eine Kompiliereinheit sind... die Reihenfolge der Kopfzeilen ist der kürzeste Weg zum Wartungsalptraum...

1 Stimmen

Sie müssen sich jedoch nicht auf die Reihenfolge der Kopfzeilen verlassen. Es spielt keine Rolle, ob sich die Header gegenseitig einschließen, vorausgesetzt, dass Sie das #define machen, bevor Sie überhaupt irgendetwas #include (zumindest unter der Annahme, dass nichts #undefs es). Dasselbe gilt für NDEBUG.

42voto

sellibitze Punkte 26706

Da die offizielle Standardbibliothek die Konstante PI nicht definiert, müssen Sie sie selbst definieren. Die Antwort auf Ihre Frage "Wie kann ich PI erhalten, ohne es manuell zu definieren?" lautet also: "Gar nicht - oder Sie sind auf compilerspezifische Erweiterungen angewiesen.". Wenn du dir keine Sorgen um die Portabilität machst, kannst du im Handbuch deines Compilers nachsehen.

Mit C++ können Sie schreiben

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

aber die Initialisierung dieser Konstante ist nicht garantiert statisch. Der G++-Compiler behandelt diese mathematischen Funktionen jedoch als intrinsische Funktionen und ist in der Lage, diesen konstanten Ausdruck zur Kompilierzeit zu berechnen.

9 Stimmen

Ich verwende in der Regel acos(-1), wie Sie sagen, werden sie zur Kompilierzeit ausgewertet. Als ich M_PI, acos(-1) und atan(1)*4 getestet habe, erhielt ich identische Werte.

3 Stimmen

Der traditionelle Weg ist die Verwendung von 4*atan(1.) : atan ist einfach zu implementieren und die Multiplikation mit 4 ist eine exakte Operation. Natürlich falten moderne Compiler alle Konstanten mit der geforderten Genauigkeit, und es ist durchaus sinnvoll, die acos(-1) oder sogar std::abs(std::arg(std::complex<double>(-1.,0.))) was die Umkehrung der Eulerschen Formel ist und daher ästhetisch ansprechender ist, als es scheint (ich habe hinzugefügt abs denn ich weiß nicht mehr, wie die komplexe Ebene geschnitten wird oder ob sie überhaupt definiert ist).

1 Stimmen

Nur damit niemand versehentlich denkt, dass Sie es ernst meinen (schon wieder-_-'). Dies ist eine schreckliche Lösung. Die atan-Implementierung ist nicht durch den Standard definiert, d.h. sie ist implementierungs- und möglicherweise hw-abhängig. Das bedeutet, dass die Numerik schrecklich sein kann, was bedeutet, dass Sie vielleicht besser dran sind, wenn Sie 3.14 im Allgemeinen verwenden. Außerdem ist sie möglicherweise sehr langsam, sogar für die Spezialfälle.

41voto

Joakim Punkte 341

Von der Posix-Manualseite von math.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

5 Stimmen

Gute Antwort, aber der Link ist tot. Ich schlage vor diese stattdessen.

29voto

RichieHindle Punkte 256891

In Standard-C++ gibt es keine Konstante für PI.

Viele C++-Compiler definieren M_PI en cmath (oder in math.h für C) als eine nicht standardisierte Erweiterung. Sie müssen möglicherweise #define _USE_MATH_DEFINES bevor Sie es sehen können.

1 Stimmen

Gute Nachrichten, liebe Leute! Das tut es jetzt bzw. wird es bald tun. eel.is/c++draft/numbers -- Ich mag nicht alle ihre Entscheidungen, aber als Konzept (kein Wortspiel beabsichtigt) ist es längst überfällig.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X