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.

5voto

Jon Guiton Punkte 1330

Einige elegante Lösungen. Ich bezweifle allerdings, dass die Genauigkeit der trigonometrischen Funktionen mit der Genauigkeit der Typen übereinstimmt. Für diejenigen, die es vorziehen, einen konstanten Wert zu schreiben, funktioniert dies für g++ :-

template<class T>
class X {
public:
            static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}

Die Genauigkeit von 256 Dezimalstellen sollte für jeden zukünftigen Long-Long-Long-Double-Typ ausreichend sein. Wenn mehr benötigt werden, besuchen Sie https://www.piday.org/million/ .

4voto

Jeroen Lammertink Punkte 355

Werte wie M_PI, M_PI_2, M_PI_4 usw. gehören nicht zum C++-Standard, so dass ein constexpr eine bessere Lösung zu sein scheint. Es können verschiedene const-Ausdrücke formuliert werden, die denselben Pi berechnen, und ich frage mich, ob sie (alle) die volle Genauigkeit bieten. Im C++-Standard wird nicht ausdrücklich erwähnt, wie pi zu berechnen ist. Daher neige ich dazu, auf die manuelle Definition von pi zurückzugreifen. Ich möchte die folgende Lösung vorstellen, die alle Arten von Brüchen von pi mit voller Genauigkeit unterstützt.

#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;
}

2 Stimmen

Sehr schön. Es könnte notwendig sein, ein "l" oder "L" am Ende dieser Nummer zu haben. Mein Compiler gcc auf Linux warnt mich vor einer Verengung.

3voto

gjerich Punkte 341
#include <cmath>
const long double pi = acos(-1.L);

0 Stimmen

Ich hatte die offensichtliche Frage "warum nicht constexpr?" und jemand hat dies bereits beantwortet auf stackoverflow.com/questions/32814678/ die für jemanden nützlich sein könnten.

2voto

Ich kann Pi schon seit dem College (vielleicht sogar seit der High School) bis auf 11 Stellen auswendig, daher ist dies immer mein bevorzugter Ansatz:

#ifndef PI
#define PI 3.14159265359
#endif

1 Stimmen

Dies ist keine gute Lösung, da die Standard-Header mit einer für ihre C++-Implementierung geeigneten Präzision definiert werden. Das heißt, sie verwenden so viele Ziffern wie nötig, um so genau wie möglich zu sein. Sie können auch ein hexadezimales Format verwenden, um Rundungsprobleme bei der Umwandlung von Dezimalzahlen in das interne Gleitkommaformat zu vermeiden. Die Standard-Header sollten bevorzugt werden, und wenn man sich selbst definieren will, dann mit mehr Stellen.

0 Stimmen

Was genau hat eine "C++-Implementierung" mit der Anzahl der Ziffern von Pi zu tun? Beziehen Sie sich auf die Bitbreite der Register?

1 Stimmen

Das ist buchstäblich die einzige gute Antwort auf diese Frage. Sie enthält keine esoterischen Header-Dateien, führt keine weiteren mathematischen Trigonometrie-Operationen durch und ist nicht auf Assembler-Code angewiesen. Sie nutzt einfach die guten altmodischen amerikanischen Highschool-Mathekenntnisse. Hut ab, guter Mann!

2voto

Simon Punkte 1

Ich mag #defines nicht, da sie einfache Textersetzungen ohne Typsicherheit sind. Sie können auch Probleme mit Ausdrücken verursachen, wenn Klammern weggelassen werden, z.B.

#define T_PI 2*PI

sollte wirklich sein

#define T_PI (2*PI)

Meine derzeitige Lösung für dieses Problem ist die Verwendung fest kodierter Werte für Konstanten, z. B. in my_constants.hxx

namespace Constants {
    constexpr double PI = 3.141... ;
}

Ich kodiere die Werte jedoch nicht fest (da ich diesen Ansatz auch nicht mag), sondern ich verwende ein separates Fortran-Programm, um diese Datei zu schreiben. Ich verwende Fortran, weil es Vierfachpräzision vollständig unterstützt (C++ unter VisualStudio nicht) und trig-Funktionen das C++-Äquivalent zu constexpr sind. Z.B..

real(8), parameter :: pi = 4*atan(1.0d0)

Zweifellos lassen sich auch andere Sprachen für dieselbe Aufgabe verwenden.

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