546 votes

Comment utiliser la constante PI en C++

Je veux utiliser la constante PI et les fonctions trigonométriques dans un programme C++. J'obtiens les fonctions trigonométriques avec include <math.h> . Cependant, il ne semble pas y avoir de définition de PI dans ce fichier d'en-tête.

Comment puis-je obtenir PI sans le définir manuellement ?

3 votes

@tiwo, est-ce que vous demandez quelle est la différence entre 3.14 , 3.141592 et atan(1) * 4 ?

27 votes

À titre d'information, cmath devrait être utilisé en C++ au lieu de math.h, qui est pour le C.

4 votes

Librement lié : voir cise.ufl.edu/~manuel/obfuscate/pi.c sur la façon de calculer la valeur de PI directement à partir de la définition.

614voto

fritzone Points 9925

Sur certaines plates-formes (surtout les plus anciennes) (voir les commentaires ci-dessous), vous devrez peut-être

#define _USE_MATH_DEFINES

et ensuite inclure le fichier d'en-tête nécessaire :

#include <math.h>

et la valeur de pi est accessible via :

M_PI

Dans mon math.h (2014), il est défini comme suit :

# define M_PI           3.14159265358979323846  /* pi */

mais vérifiez votre math.h pour en savoir plus. Un extrait de l'"ancien" math.h (en 2009) :

/* Define _USE_MATH_DEFINES before including math.h to expose these macro
 * definitions for common math constants.  These are placed under an #ifdef
 * since these commonly-defined names are not part of the C/C++ standards.
 */

Cependant :

  1. sur les plates-formes plus récentes (au moins sur mon Ubuntu 14.04 64 bits), je n'ai pas besoin de définir l'élément _USE_MATH_DEFINES

  2. Sur les plateformes Linux (récentes), il existe long double sont également fournies en tant qu'extension GNU :

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */

59 votes

#define _USE_MATH_DEFINES suivi par #include <math.h> définit M_PI en c++ visuel. Merci.

3 votes

Fonctionne également avec les en-têtes cygwin.

31 votes

Vous pouvez toujours inclure cmath au lieu de math.h .

183voto

Konamiman Points 20578

Pi peut être calculé comme suit atan(1)*4 . Vous pourriez calculer la valeur de cette manière et la mettre en cache.

84 votes

Pour les utilisateurs de c++11 : constexpr double pi() { return std::atan(1)*4; }

48 votes

-1 : Ne fonctionne que si atan(1)*4 == 3.141592653589793238462643383279502884 (en gros). Je ne parierais pas là-dessus. Soyez normal et utilisez un littéral brut pour définir la constante. Pourquoi perdre de la précision quand vous n'en avez pas besoin ?

4 votes

@ThomasEding - mon math.h lecture des fichiers #define M_PI 3.14159265358979323846 (si ANSI strict).

116voto

BuschnicK Points 1593

Vous pouvez également utiliser boost, qui définit les constantes mathématiques importantes avec une précision maximale pour le type demandé (par exemple, float vs double).

const double pi = boost::math::constants::pi<double>();

Consultez le documentation sur le boost pour d'autres exemples.

220 votes

Boost : Augmenter la complexité déjà inutile du C++ depuis 1999 !

49 votes

Accrocheur et en partie vrai. D'un autre côté, le boost peut être d'une utilité phénoménale par moments...

0 votes

Cela ne fonctionnera pas si vous voulez définir une variable globale PI. Vous obtiendrez une erreur en criant que 'pi' is not declared in this scope . Je suis novice en matière de C++, donc s'il existe un moyen de contourner ce problème, je ne le connais pas.

52voto

Matthieu M. Points 101624

Plutôt que d'écrire

#define _USE_MATH_DEFINES

Je recommande d'utiliser -D_USE_MATH_DEFINES ou /D_USE_MATH_DEFINES en fonction de votre compilateur.

De cette façon, vous êtes assuré que même si quelqu'un inclut l'en-tête avant vous (et sans #define), vous aurez toujours les constantes au lieu d'une obscure erreur de compilation que vous mettrez des siècles à retrouver.

0 votes

Bon conseil. Si "vous" êtes une unité de compilation, vous pouvez bien sûr vous assurer que la macro est définie avant toute inclusion. Mais si "vous" êtes un fichier d'en-tête, vous ne pouvez rien faire.

3 votes

En fait, même si "vous" êtes une unité de compilation... dépendre de l'ordre des en-têtes est le chemin le plus court vers le cauchemar de la maintenance...

1 votes

Vous ne devez cependant pas dépendre de l'ordre des en-têtes. Il importe peu que les en-têtes s'incluent les uns les autres, à condition que vous fassiez le #define avant de #inclure quoi que ce soit (du moins, en supposant que rien ne le #undefie). La même chose s'applique à NDEBUG.

51voto

Alex Points 331

Je vous recommande de simplement taper pi à la précision dont vous avez besoin. Cela n'ajouterait aucun temps de calcul à votre exécution, et ce serait portable sans utiliser d'en-têtes ou de #defines. Calculer acos ou atan est toujours plus coûteux que d'utiliser une valeur précalculée.

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

29 votes

C'est un excellent exemple de la raison pour laquelle nous ne devrions pas adopter cette approche, les gens font des erreurs, arrondissent, copient et collent, etc. Je pense que l'utilisation de M_PI est la bonne approche.

13 votes

Si l'on effectue cette opération en C++11, il faut faire en sorte que l'option const a constexpr .

4 votes

@nacho4d Moi aussi je préfère M_PI s'il est disponible, mais tous les systèmes ne sont pas compatibles POSIX. Je pense que cette approche est meilleure que la méthode 4*atan(1) pour les cas où M_PI n'est pas disponible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X