Il y a un problème plutôt idiot avec le nombre pi en C et C ++. Autant que je sache, M_PI
défini dans math.h
n'est requis par aucune norme.
Les nouvelles normes C ++ ont introduit beaucoup de mathématiques compliquées dans la bibliothèque standard - des fonctions hyperboliques std::hermite
et std::cyl_bessel_i
différents générateurs de nombres aléatoires, etc.
L'une des «nouvelles» normes a-t-elle introduit une constante pour pi? Sinon, pourquoi? Comment tout ce calcul compliqué fonctionne-t-il sans cela?
J'ai connaissance de questions similaires sur pi en C ++ (elles datent de plusieurs années et ont des standards); J'aimerais connaître l'état actuel du problème.
Je suis également très intéressé par pourquoi oh pourquoi C ++ n'a toujours pas de constante pi mais a beaucoup de mathématiques plus compliquées.
UPD: Je sais que je peux définir pi moi-même comme 4 * atan (1) ou acos (1) ou double pi = 3,14. Sûr. Mais pourquoi dois-je encore le faire en 2018? Comment les fonctions mathématiques standard fonctionnent-elles sans pi?
UPD2: Selon ce rapport de voyage pour la réunion du comité C ++ en juillet 2019 à Cologne, la proposition P0631 (constantes mathématiques) a été acceptée dans C ++ 20. Il semble donc que nous aurons enfin le numéro pi dans la bibliothèque standard!
Réponses:
Jusqu'au C ++ 17 inclus, pi n'est pas une constante introduite dans le langage, et c'est une douleur dans le cou.
J'ai la chance d'utiliser boost et ils définissent pi avec un nombre suffisamment grand de décimales pour même un 128 bits
long double
.Si vous n'utilisez pas Boost, codez-le vous-même. Le définir avec une fonction trigonométrique est tentant, mais si vous faites cela, vous ne pouvez pas en faire un
constexpr
. La précision des fonctions trigonométriques est également garanti par aucun savoir standard I ( cf .std::sqrt
), Donc vraiment vous êtes sur un terrain dangereux reposant en effet sur une telle fonction.Il existe un moyen d'obtenir une
constexpr
valeur pour pi en utilisant la métaprogrammation: voir http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/De C ++ 20, quelques bonnes nouvelles. Il existe une définition pour pi . C ++ 20 ajoute des constantes mathématiques dans
<numbers>
. Par exemplestd::numbers::pi
est undouble
type.Référence: https://en.cppreference.com/w/cpp/numeric/constants
la source
constexpr
malheureusement, c'est pourquoi je dis "Le définir avec une fonction trigonométrique est pénible"double
(ou à un nombre ridicule si vous vous souciez des doubles hypothétiques très longs).fsin
instruction "d'environ 1,37 quintillion d'unités à la dernière place, laissant moins de quatre bits corrects" , et c'est pire encore pour les entrées volumineuses où la réduction de la portée s’enroule plusieurs fois. C'est quelque peu tangentiel aux constantes utilisées pourlong double
en C ++, mais parfait quand même.Comme d'autres l'ont dit, il n'y en a pas,
std::pi
mais si vous voulez unePI
valeur précise , vous pouvez utiliser:Cela suppose que votre implémentation C ++ produit une valeur correctement arrondie de PI from
acos(-1.0)
, ce qui est courant mais non garanti .Ce n'est pas le cas
constexpr
, mais en pratique, l'optimisation des compilateurs comme gcc et clang l'évalue au moment de la compilation. Cependant, ilconst
est important que l'optimiseur fasse du bon travail.la source
acos()
fonction a une pente infinie àx = -1
. Par conséquent, cette méthode repose sur l'acos()
implémentation pour intercepter explicitement le cas d'un-1
argument précis et renvoyer directement la constante correcte. Mieux vaut utiliser quelque chose comme4*atan(1)
qui est mathématiquement beaucoup plus robuste (une pente àx = 1
et une multiplication par 4 sont toujours précises avec des mathématiques en virgule flottante).std::acos
dans une expression constante. clang signale cela comme une erreur. Veuillez noter qu'il s'agit d'une extension non conforme et qu'elle devrait éventuellement être corrigée dans gcc. Veuillez vous référer à cette réponse pour plus de détails.Jusqu'en C ++ 20, non, aucune des normes n'introduit la constante qui représenterait le nombre pi (π). Vous pouvez approximer le nombre dans votre code:
D'autres langages tels que C # ont la constante déclarée dans leurs bibliothèques.
Mise à jour: A partir du C ++ 20, il y a en effet une
pi
constante déclarée à l'intérieur de l'en-<numbers>
tête. Il est accessible via:std::numbers::pi
.la source
inline
pour C ++ 17 +.double
. C # est facile puisque ledouble
type est fixe. Si j'étais membre du comité des normes C ++, je proposerais quelque chose commestd::constants<double>::pi
std::numeric_limits<double>::is_iec559;
dans ce cas. Ce qui, je l'avoue, est ce que j'ai dans mon "master header". Notez que formellement, vous devez vérifier tous les types à virgule flottante séparément. Ce n'est pas parce que l'un est IEEE754 qu'ils le sont tous.M_PI
est défini par "un standard", sinon un standard de langage : POSIX avec l'extension X / Open System Interfaces (qui est très couramment supportée et requise pour la marque UNIX officielle).On ne sait pas (toujours) ce que sera en C ++ 20, mais puisque vous l'avez demandé: il aura probablement de telles constantes . Le document a été fusionné lors de la dernière série de fonctionnalités C ++ 20 (pour le projet de comité en août 2019).
Plus précisément, il y aura à la fois
std::numbers::pi
(de typedouble
) et un modèle de variable que vous pouvez utiliser si vous voulez un type à virgule flottante différent, par exemplestd::numbers::pi_v<float>
. La liste complète des constantes peut être vue dans [numbers.syn] .la source
Ce n'est évidemment pas une bonne idée car il n'y a pas de type évident avec lequel définir pi qui soit universellement applicable à travers les domaines.
Pi est, bien sûr, un nombre irrationnel, donc il ne peut être correctement représenté par aucun type C ++. Vous pourriez dire que l'approche naturelle consiste donc à le définir dans le plus grand type à virgule flottante disponible. Cependant, la taille du plus grand type à virgule flottante standard
long double
n'est pas définie par la norme C ++, de sorte que la valeur de la constante varie d'un système à l'autre. Pire encore, pour tout programme dans lequel le type de travail n'était pas ce type le plus grand, la définition de pi serait inappropriée car elle imposerait un coût de performance à chaque utilisation de pi.Il est également trivial pour tout programmeur de trouver la valeur de pi et de définir sa propre constante utilisable, donc cela ne fournit pas un grand avantage de l'inclure dans les en-têtes mathématiques.
la source
pi
une constante polymorphe est la voie à suivre - dans un langage avec l'inférence de type Hindley-Milner. Dans Haskell, nous l'avons toujours faitpi :: Floating a => a
, donc celapi
aurait automatiquement la valeur3.1415927
dans unFloat
contexte,3.141592653589793
dans unDouble
contexte etπ
dans un contexte de calcul symbolique. Mais les gens aimeraient-ils vraiment avoir à instancier explicitement le paramètre de modèle? Cela semble un peu gênant, surtout si unelong double
implémentation fixe donnerait des résultats identiques dans la plupart des applications.auto a = pi<float>;
est tout à fait bien, certainement plus lisible que notoire4*atan(1)
Modifié - Pour supprimer le terme nécessaire, car il s'est avéré controversé. C'est trop un terme absolu.
C ++ est un langage volumineux et complexe, c'est pourquoi le Comité des normes n'inclut que les éléments fortement requis . Autant que possible est laissé aux bibliothèques standard non linguistiques ... comme Boost.
boost :: math :: constantes
la source
std::hermite
etstd::cyl_bessel_i
etstd::cosh
etstd::mersenne_twister_engine
etstd::ranlux48
etstd::cauchy_distribution
etstd::assoc_laguerre
etstd::beta
tous étaient absolument nécessaires, nous les utilisons tous tous les jours!