일부 C ++ 프로그램에서 PI 상수 및 삼각 함수를 사용하고 싶습니다. 삼각 함수를include <math.h>
. 그러나이 헤더 파일에는 PI에 대한 정의가없는 것 같습니다.
PI를 수동으로 정의하지 않고 어떻게 얻을 수 있습니까?
일부 C ++ 프로그램에서 PI 상수 및 삼각 함수를 사용하고 싶습니다. 삼각 함수를include <math.h>
. 그러나이 헤더 파일에는 PI에 대한 정의가없는 것 같습니다.
PI를 수동으로 정의하지 않고 어떻게 얻을 수 있습니까?
답변:
일부 (특히 오래된) 플랫폼 (아래 주석 참조)에서 다음을 수행해야 할 수도 있습니다.
#define _USE_MATH_DEFINES
필요한 헤더 파일을 포함하십시오.
#include <math.h>
pi의 값은 다음을 통해 액세스 할 수 있습니다.
M_PI
내 math.h
(2014)에서는 다음과 같이 정의됩니다.
# define M_PI 3.14159265358979323846 /* pi */
하지만 math.h
더 확인하십시오 . "이전"에서 추출한 내용 math.h
(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.
*/
하나:
최신 플랫폼 (적어도 내 64 비트 Ubuntu 14.04에서는)에서 _USE_MATH_DEFINES
(최근) Linux 플랫폼에는 long double
GNU 확장으로 제공된 값도 있습니다.
# define M_PIl 3.141592653589793238462643383279502884L /* pi */
#define _USE_MATH_DEFINES
Visual C ++에서 #include <math.h>
정의 M_PI
가 뒤 따릅니다 . 감사.
cmath
대신에 항상 포함 할 수 있습니다 math.h
.
_USE_MATH_DEFINES
GCC가 불만을 제기하는지 여부 를 정의한 후에도 정의 할 수 없는 정의되어 있기 때문에 __STRICT_ANSI__
(아마도 당신이 -pedantic
또는 -std=c++11
) M_PI
정의 하지 않기 때문에 정의 하지 마십시오 -D__STRICT_ANSI__
. 직접 정의 할 때 매크로 대신 C ++이기 때문에해야합니다 constexpr auto M_PI = 3.14159265358979323846;
.
Pi는로 계산할 수 있습니다 atan(1)*4
. 이 방법으로 값을 계산하고 캐시 할 수 있습니다.
constexpr double pi() { return std::atan(1)*4; }
atan(1)*4 == 3.141592653589793238462643383279502884
(대략 말하면) 작동합니다 . 나는 내기하지 않을 것입니다. 정상이고 원시 리터럴을 사용하여 상수를 정의하십시오. 왜 필요하지 않을 때 정밀도를 잃습니까?
atan2(0, -1);
.
atan
는 아닙니다 constexpr
.
acos(-1)
, 대신에 대한 필요성을 atan2
.
요청 된 유형 (예 : float vs double)에 대해 최대 정확도로 중요한 수학 상수를 정의하는 boost를 사용할 수도 있습니다.
const double pi = boost::math::constants::pi<double>();
더 많은 예제 는 부스트 문서 를 확인하십시오 .
not gonna use libs
의견은 해충이며 아마도 C ++로 작성된 나쁜 소프트웨어의 가장 큰 이유 일 것입니다.
대신 FPU 유닛 온 칩에서 가져 오십시오.
double get_PI()
{
double pi;
__asm
{
fldpi
fstp pi
}
return pi;
}
double PI = get_PI();
필요한 정밀도로 pi를 입력하는 것이 좋습니다. 이렇게하면 계산에 계산 시간이 추가되지 않으며 헤더 나 #defines를 사용하지 않고도 이식 가능합니다. acos 또는 atan을 계산하는 것은 사전 계산 된 값을 사용하는 것보다 항상 비쌉니다.
const double PI =3.141592653589793238463;
const float PI_F=3.14159265358979f;
const
a를 만드십시오 constexpr
.
constexpr
.
쓰기보다는
#define _USE_MATH_DEFINES
내가 사용하는 것이 좋습니다 것 -D_USE_MATH_DEFINES
또는/D_USE_MATH_DEFINES
컴파일러를 컴파일러에 따라 합니다.
이렇게하면 헤더를 포함하기 전에 누군가가 헤더를 포함하는 경우에도 (#define이없는 경우) 추적하는 데 오랜 시간이 걸리는 모호한 컴파일러 오류 대신 상수가 여전히 유지됩니다.
<cmath>
다른 장소에서 사용 하면 큰 고통이됩니다 (특히 포함 된 다른 라이브러리에 포함 된 경우). 헤더 가드 외부에 해당 부분을 배치하면 훨씬 나아졌지 만 지금은 그 일을 많이 할 수 없습니다. 컴파일러 지시문은 실제로 잘 작동합니다.
공식 표준 라이브러리는 상수 PI를 정의하지 않으므로 직접 정의해야합니다. 따라서 귀하의 질문에 대한 답변은 "PI를 수동으로 정의하지 않고 어떻게 얻을 수 있습니까?" "아니요-또는 컴파일러 특정 확장에 의존합니다." 이식성에 대해 걱정하지 않는다면 컴파일러 매뉴얼에서 확인할 수 있습니다.
C ++를 사용하면 쓸 수 있습니다
const double PI = std::atan(1.0)*4;
그러나이 상수의 초기화가 정적 인 것은 아닙니다. 그러나 G ++ 컴파일러는 이러한 수학 함수를 내장 함수로 처리하며 컴파일시이 상수 표현식을 계산할 수 있습니다.
4*atan(1.)
: atan
구현하기 쉽고 4를 곱하면 정확한 연산입니다. 물론, 현대 컴파일러는 배에 필요한 정밀도로 모든 상수 (배 목표), 그리고 그것을 사용하는 완벽하게 합리적 acos(-1)
또는 std::abs(std::arg(std::complex<double>(-1.,0.)))
오일러의 공식의 역이며, 따라서 더 미학적 (I 추가 한 보인다보다 기쁘게하는 abs
내가 '돈 때문에 복잡한 평면이 어떻게 절단되는지 또는 그것이 정의 된 경우를 기억하십시오).
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
C ++ 20 std::numbers::pi
마침내 도착했습니다 : http://eel.is/c++draft/numbers
사용법은 다음과 같습니다.
#include <numbers>
#include <iostream>
int main() {
std::cout << std::numbers::pi << std::endl;
}
지원이 GCC, GCC 9.1.0에 도달하면 시도해 보겠습니다. g++-9 -std=c++2a
아직 지원하지 않을 .
수락 된 제안은 다음을 설명합니다.
5.0. “헤더”[헤더] 테이블 [tab : cpp.library.headers]에서 새로운
<math>
헤더를 추가해야합니다.[...]
namespace std { namespace math { template<typename T > inline constexpr T pi_v = unspecified; inline constexpr double pi = pi_v<double>;
또한이 std::numbers::e
과정 :-) 어떻게 C ++로 전원 오일러 상수 또는 오일러을 계산하기 위해?
이 상수는 C ++ 14 변수 템플릿 기능을 사용합니다. C ++ 14 변수 템플릿 : 목적은 무엇입니까? 사용 예가 있습니까?
이전 버전의 초안에서 상수는 std::math::pi
다음과 같습니다. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf
표준 C ++에는 PI에 대한 상수가 없습니다.
많은 C ++ 컴파일러 정의 M_PI
에 cmath
(또는에서 math.h
표준이 아닌 확장으로 C의 경우). 당신이 #define _USE_MATH_DEFINES
그것을보기 전에해야 할 수도 있습니다 .
나는 할것이다
template<typename T>
T const pi = std::acos(-T(1));
또는
template<typename T>
T const pi = std::arg(-std::log(T(2)));
나는 것 없는 당신이 필요로하는 정밀도에 π를 입력 . 그게 무슨 뜻입니까? 당신이 필요로하는 정밀도 의 정밀도입니다 T
만, 우리는 약 아무것도 몰라T
.
당신은 말할 수 있습니다 : 당신은 무엇에 대해 이야기하고 있습니까? T
것 float
, double
또는 long double
. 그래서, 단지의 정밀도를 입력 long double
, 즉,
template<typename T>
T const pi = static_cast<T>(/* long double precision π */);
그러나 미래에는 표준보다 새로운 정밀도를 가진 새로운 부동 소수점 유형이 없다는 것을 정말로 알고 long double
있습니까? 당신은하지 않습니다.
이것이 첫 번째 솔루션이 아름다운 이유입니다. 표준이 새로운 유형의 삼각 함수에 과부하가 걸리는 것을 확신 할 수 있습니다.
초기화시 삼각 함수의 평가가 성능 저하라고 말하지 마십시오.
arg(log(x)) == π
모두 를 위해 0 < x < 1
.
모든 기반을 다루는 프로젝트의 공통 헤더 중 하나에서 다음을 사용합니다.
#define _USE_MATH_DEFINES
#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
#ifndef M_PIl
#define M_PIl (3.14159265358979323846264338327950288)
#endif
참고로, 아래의 모든 컴파일러는 포함하면 M_PI 및 M_PIl 상수를 정의합니다 <cmath>
. VC ++에만 필요한`#define _USE_MATH_DEFINES를 추가 할 필요는 없습니다.
x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+
M_PI
필요없이 정의합니다_USE_MATH_DEFINES
나는 const double PI = 2*acos(0.0);
모든 구현이 당신을 위해 그것을 제공하는 것은 아니기 때문에 일반적으로 내 자신을 정의하는 것을 선호 합니다.
이 함수가 런타임에 호출되는지 또는 컴파일 타임에 정적인지에 대한 질문은 일반적으로 한 번만 발생하기 때문에 문제가되지 않습니다.
double x = pi * 1.5;
예 : 등). 엄격한 루프에서 바삭 바삭한 수학에서 PI를 사용하려는 경우 컴파일러에 값을 알려주는 것이 좋습니다.
방금 C ++ 14 이상에 대한 유용한 팁이있는 Danny Kalev의 기사 를 보았습니다 .
template<typename T>
constexpr T pi = T(3.1415926535897932385);
나는 템플릿이 유형에 따라 사용할 수 있기 때문에 이것이 매우 멋지다고 생각했다.
template<typename T>
T circular_area(T r) {
return pi<T> * r * r;
}
double darea= circular_area(5.5);//uses pi<double>
float farea= circular_area(5.5f);//uses pi<float>
M_PI, M_PI_2, M_PI_4 등과 같은 값은 표준 C ++이 아니므로 constexpr이 더 나은 솔루션으로 보입니다. 동일한 pi를 계산하는 다른 const 표현식을 공식화 할 수 있으며, 전체 정확도를 제공하는지 여부와 관련이 있습니다. C ++ 표준에는 pi 계산 방법이 명시 적으로 언급되어 있지 않습니다. 따라서 수동으로 pi를 정의하는 경향이 있습니다. 나는 모든 종류의 pi를 완벽하게 지원하는 솔루션을 아래에서 공유하고 싶습니다.
#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;
}
Windows (cygwin + g ++) 에서 in -D_XOPEN_SOURCE=500
의 정의를 처리하기 위해 전 처리기에 대한 플래그를 추가해야한다는 것을 알았습니다 .M_PI
math.h
M_PI
특정 플랫폼에서 작업하는 데 필요한 단계를 제공하는 완전 독립형 답변입니다 . 그것은 다른 플랫폼에 대한 답변이 더 이상 다른 플랫폼에 대한 답변이 아니라는 것입니다.
C ++ 14를 사용하면 static constexpr auto pi = acos(-1);
std::acos
이 아닙니다 constexpr
. 따라서 코드가 컴파일되지 않습니다.
acos
가 아니기 때문에 g ++가 잘못 되었고 C ++ 17에서도 constexpr
제안되지 않았 음constexpr
constexpr
있습니까? 분명히 아닙니다 : stackoverflow.com/questions/17347935/constexpr-math-functions
constexpr
(예 : github.com/kthohr/gcem ). 그러나 동일한 이름의 C 함수와 역 호환되지 않으므로 이전 이름을 대체 할 수 없습니다.
일부 우아한 솔루션. 삼각 함수의 정밀도는 유형의 정밀도와 같지 않습니다. 상수 값을 쓰는 것을 선호하는 사람들에게는 g ++에서 작동합니다.
template<class T>
class X {
public:
static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}
미래의 long long long double 유형에는 256 자리 십진수 정확도가 충분해야합니다. 추가 정보가 필요한 경우 https://www.piday.org/million/을 방문 하십시오 .
3.14
,3.141592
그리고atan(1) * 4
?