Die Berechnung des PI-Werts ist eines der komplexen Probleme, und Wikipedia spricht über die dafür vorgenommenen Annäherungen und sagt, es sei schwierig, den PI genau zu berechnen.
Wie berechnet C PI? Berechnet es jedes Mal oder verwendet es einen weniger genauen festen Wert?
double
) sollten ausreichen, um den Durchmesser des Sonnensystems mit einem Fehler von weniger als einer Haarbreite zu berechnen.Antworten:
In C ist Pi in math.h definiert:
#define M_PI 3.14159265358979323846
quelle
PI
in<math.h>
. POSIX gibt anM_PI
, aber eine konforme C-Implementierung definiert sie möglicherweise nicht. (POSIX stellt einige Anforderungen, die im Widerspruch zum C-Standard stehen.) Sie können dies jedoch in Ihrem eigenen Programm so definieren.M_
. Es gab auch Sachen wieM_E
,M_LN10
etc. Sie es nie zum Standard gemacht.Das, was C am nächsten kommt, um π auf eine Weise zu berechnen, die für Anwendungen direkt sichtbar ist, ist
acos(-1)
oder ähnlich. Dies geschieht fast immer mit polynomialen / rationalen Näherungen für die zu berechnende Funktion (entweder in C oder durch den FPU-Mikrocode).Allerdings ist eine interessante Frage ist , dass die trigonometrischen Funktionen Berechnung (
sin
,cos
, undtan
) erfordert Reduktion ihres Arguments modulo 2π. Da 2π kein diadisches Rational (und nicht einmal Rational) ist, kann es in keinem Gleitkommatyp dargestellt werden, und daher führt die Verwendung einer Annäherung des Wertes zu einer katastrophalen Fehlerakkumulation für große Argumente (z. B. ifx
is1e12
und2*M_PI
unterscheidet sich von 2π) durch ε,fmod(x,2*M_PI)
unterscheidet sich dann vom korrekten Wert von 2π um bis zu 1e12 * ε / π mal den korrekten Wert vonx
mod 2π. Das heißt, es ist völlig bedeutungslos.Eine korrekte Implementierung der Standard-Mathematikbibliothek von C hat einfach eine gigantische, sehr hochpräzise Darstellung von π, die in ihrer Quelle hartcodiert ist, um das Problem der korrekten Argumentreduktion zu lösen (und verwendet einige ausgefallene Tricks, um es nicht ganz so gigantisch zu machen ). So funktionieren die meisten / alle C-Versionen der
sin
/cos
/tan
-Funktionen. Es ist jedoch bekannt, dass bestimmte Implementierungen (wie glibc) Assembly-Implementierungen auf einigen CPUs (wie x86) verwenden und keine korrekte Argumentreduktion durchführen, was zu völlig unsinnigen Ausgaben führt. (Übrigens läuft der falsche ASM normalerweise ungefähr so schnell wie der richtige C-Code für kleine Argumente.)quelle
x
fast bedeutungslos ist und höchstwahrscheinlich ein Fehler im Code ist, der die Sinusfunktion verwendet. Wennx
es so groß ist, dass es eine Ganzzahl wird, können Sie nur etwa 6 Wertex
pro Sinusperiode darstellen. Natürlich kann man eine finden,y
die die Bedingung erfüllt, und das ist schön, aber ich bezweifle, dass es eine nützliche Anwendung für die Berechnung von Sinuszahlen von ganzen Zahlen gibt.x
wäre eine Analyse, wie schnell dieser "Epsilon-Fehler" mit zunimmtx
. Wenn es einen signifikanten Fehler bei gibt1000*M_PI
, dann verstehe ich das Problem und würde Ihnen voll und ganz zustimmen.fmod(x,2*M_PI)
wächst der Fehler von vs dem korrekten argumentreduzierten Wert linear in der Größe vonx
. Wenn Sie also 1ulp fürx
etwas außerhalb des Einheitskreises annehmen , würden Sie sich etwas wie 1000ulp für ansehen1000*M_PI
. Nahe den Nullensin
ist nahezu linear mit der Steigung 1, sodass die Anzahl der ulp im Argument im Ergebnis direkt in ulp übersetzt wird.sin(2^n)
für große Werte vonn
; Ich erinnere mich jedoch nicht, was sie auf Anhieb sind.Definieren Sie einfach:
#define M_PI acos(-1.0)
Es sollte Ihnen die genaue PI-Nummer geben, mit der mathematische Funktionen arbeiten. Wenn sie also den PI-Wert ändern, mit dem sie in Tangente, Cosinus oder Sinus arbeiten, sollte Ihr Programm immer auf dem neuesten Stand sein;)
quelle
acos
Funktion ist Teil der eigentlichen C-Sprache.Trotzdem haben Sie keine unbegrenzte Genauigkeit, also definiert C eine Konstante auf folgende Weise:
#define PI 3.14159265358979323846
Importieren Sie math.h, um dies zu verwenden
quelle
M_PI
nicht in C. Es ist Teil der XSI-Erweiterungsoption in POSIX.Abhängig von der Bibliothek, in der Sie die standardmäßigen GNU C-vordefinierten mathematischen Konstanten verwenden, finden Sie hier ... https://www.gnu.org/software/libc/manual/html_node/Mathematical-Constants.html
Sie haben sie bereits. Warum sollten Sie sie neu definieren? Ihre System-Desktop-Rechner haben sie wahrscheinlich und sind sogar noch genauer, sodass Sie sicher sein können, dass Sie nicht mit vorhandenen definierten in Konflikt stehen, um beim Kompilieren von Warnungen zu sparen, da diese in der Regel Standardeinstellungen für solche Dinge erhalten. Genießen!
quelle
Ich weiß nicht genau, wie
C
manPI
direkt berechnet, da ich besser vertraut binC++
alsC
; Sie können jedoch entweder eine vordefinierteC
macro
oder eineconst
solche haben:#define PI 3.14159265359..... const float PI = 3.14159265359..... const double PI = 3.14159265359..... /* If your machine,os & compiler supports the long double */ const long double PI = 3.14159265359.....
oder Sie können es mit einer dieser beiden Formeln berechnen:
#define M_PI acos(-1.0); #define M_PI (4.0 * atan(1.0)); // tan(pi/4) = 1 or acos(-1)
IMHO bin ich nicht 100% sicher, aber ich denke,
atan()
ist billiger alsacos()
.quelle
#define CONSTANT numberHere
?C
ist sehr rostig, da es fast 20 Jahre her ist, seit ich daran gearbeitet habe und die Tatsache, dass ich es meistens benutzt habeC++
. Ich hatte diese Frage ursprünglich mit einerC++
Perspektive beantwortet ... Ich habe die Antwort aktualisiert, um dies zu berücksichtigen ...