C ++ 11, 14, 17 또는 20은 파이에 대한 표준 상수를 도입합니까?


170

C와 C ++의 숫자 pi에는 다소 어리석은 문제가 있습니다. 멀리로 나는 알고 M_PI에 정의 된 math.h표준에 의해 필요하지 않습니다.

새로운 C ++ 표준은 표준 라이브러리에서 쌍곡선 함수 std::hermitestd::cyl_bessel_i다른 난수 생성기 등 의 복잡한 수학을 많이 도입했습니다 .

'새로운'표준 중 어떤 것이 파이에 대한 상수를 가져 왔습니까? 그렇지 않은 경우-왜? 이 복잡한 수학은 모두없이 어떻게 작동합니까?

C ++에서 pi에 대한 비슷한 질문을 알고 있습니다 (몇 년이고 표준이 오래되었습니다). 문제의 현재 상태를 알고 싶습니다.

C ++에 여전히 pi 상수가 없지만 더 복잡한 수학이 필요한지에 관심이 있습니다.

UPD : pi를 4 * atan (1) 또는 acos (1) 또는 double pi = 3.14로 정의 할 수 있다는 것을 알고 있습니다. 확실한. 그러나 2018 년에 왜 여전히해야합니까? 표준 수학 함수는 pi없이 어떻게 작동합니까?

UPD2 : 쾰른에서 2019 년 7 월 C ++위원회 회의에 대한 여행 보고서에 따르면 제안 P0631 (수 상수)이 C ++ 20으로 수락되었습니다. 결국에는 표준 라이브러리에 숫자 pi가있는 것처럼 보입니다!


Best platform independent pi constant 와 같은 오래된 질문이 있습니까? . 당신이 그들이 구식이라고 걱정한다면 당신은 항상 C ++ 17 등을 기반으로 답변을 요구하는 그들 중 하나에 현상금을 설정할 수 있습니다 ... 그러면 모든 답변은 한곳에있을 것입니다. 여전히 좋은 질문이지만 왜 이것이 최신 질문이 기존 질문에 대한 현상금이되는지에 초점을 두어야 할 것입니다.
Shafik Yaghmour

C ++ 20이 내가 아는 한 pi 상수를 추가 한 이후로 새로운 답변을 추가 할 가치가 있다고 생각합니다.
Guillaume Racicot

@GuillaumeRacicot 나는 질문을 업데이트했다. 아직 공식적으로 나오지 않았으므로 C ++ 20을 해결해야하는지 확실하지 않습니다.
Amomum

@GuillaumeRacicot : 하나를 추가하는 데 조금 늦었습니다…
Davis Herring

답변:


101

C ++ 17까지 pi 는 언어에 지속적으로 도입되지 않으며 목에 통증이 있습니다.

나는 부스트를 사용한다는 점에서 운이 좋으며 128 비트조차도 충분히 많은 소수 자릿수로 pi 를 정의 long double합니다.

Boost를 사용하지 않으면 직접 하드 코딩하십시오. 삼각 함수로 정의하는 것은 유혹적이지만 그렇게하면 그것을 만들 수 없습니다 constexpr. 삼각 함수의 정확도는 (의 표준 I의 노하우에 의해 보장되지 CF . std::sqrt그래서 정말 당신이 실제로 이러한 기능에 의존하는 위험한 지상에 있습니다).

메타 프로그래밍을 사용하여 piconstexpr가치를 얻는 방법이 있습니다 : http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/


C ++ 20에서 좋은 소식이 있습니다. 가 이다 의 defininition 파이는 . C ++ 20은에 수학 상수를 추가합니다 <numbers>. 예를 들어 std::numbers::piA는 double유형입니다.

참조 : https://en.cppreference.com/w/cpp/numeric/constants


9
@Lundin : 그러나 constexpr불행히도 그럴 수는 없습니다. 그래서 "삼각 기능으로 정의하는 것은 고통
Bathsheba

9
왜 중요한가요? Pi는 상수이며 변경 또는 구현에 따라 다릅니다. 중요한 부분의 수 double(또는 가상의 긴 long double에 관심이있는 경우 어리석은 숫자 )에 값 (원하는 경우 const 객체의 값)을 쓰십시오 .
R .. GitHub 중지 지원 얼음

10
@ R .. 내가 가진 문제는 이제 어리석은 것처럼 보이지만 20 년 정도면 완전히 제 정신을 잃을 수 있습니다. 빌 게이츠의 640k가 떠오른다. 아키텍처 진화에 발 맞추어 부스트를 신뢰합니다.
Bathsheba


10
@ KonradRudolph : 범위 축소를 ​​구현하는 경우 고정밀 pi가 중요합니다. 예를 들어, 86은 x87 내부 파이 상수 (전체 64 비트 가수)이 작은 입력에 대한 최악의 에러 리드 / 이동 fsin의 지시 '개보다 적은 비트를 정정 떠나는 최하위 1.37 quintillion 단위에 대해는, " 이것은, 그리고 범위 축소가 여러 번 랩핑되는 큰 입력의 경우 훨씬 더 나쁩니다. 이것은 long doubleC ++에서 사용되는 상수에 다소 접 하지만 어쨌든 깔끔합니다.
Peter Cordes

31

다른 사람들이 말했듯이 std::pi정확한 PI가치를 원한다면 다음을 사용할 수 있습니다.

constexpr double pi = std::acos(-1);

이것은 C ++ 구현이에서 올림 된 올바른 PI 값을 생성한다고 가정 하는데acos(-1.0) , 일반적이지만 보장되지는 않습니다 .

아니야 constexpr 아니지만 실제로 gcc 및 clang과 같은 최적화 컴파일러는 컴파일 타임에 그것을 평가합니다. const그래도 옵티마이 저가 좋은 일을 하는 것이 중요하다고 선언합니다 .


2
acos()함수의 기울기가 무한대 이므로 위험합니다 x = -1. 결과적으로이 메소드는 acos()구현에 의존 하여 기본적으로 정확한 -1인수 의 경우를 명시 적으로 포착 하고 올바른 상수를 직접 리턴합니다. 4*atan(1)수학적으로 훨씬 더 강건한 것을 사용하는 것이 좋습니다 (잘 작동하는 기울기 x = 1및 4의 곱셈은 항상 부동 소수점 연산으로 정밀함).
cmaster-monica reinstate 모니카

1
std::acos상수 표현에는 사용할 수 없습니다 . clang은이를 오류로보고합니다. 이는 부적합한 확장 이며 결국 gcc에서 수정되어야합니다. 자세한 내용 은이 답변 을 참조하십시오.
badola

31

C ++ 20까지는 아니오, 숫자 pi (π)를 나타내는 상수를 소개하는 표준이 없습니다 . 코드에서 숫자를 근사 할 수 있습니다.

constexpr double pi = 3.14159265358979323846;

같은 C # 등의 다른 언어 상수가 자신의 라이브러리에 선언했다.

업데이트 : C ++ 20부터 헤더 pi안에 상수가 선언되었습니다 <numbers>. 다음을 통해 액세스합니다 : std::numbers::pi.


6
inlineC ++ 17 + 를 추가 할 수 있습니다 .
중복 제거기

8
고마워. 공감대를 가지 되, 정의가 다른 정의가있는 플랫폼에서는 여전히 부정확성에 취약합니다 double. C #은 double타입이 고정되어 있기 때문에 쉽다 . 만약 내가 C ++ 표준위원회에 있었다면 다음과 같은 것을 제안 할 것이다.std::constants<double>::pi
Bathsheba

11
@ 중복 제거기는 암묵적으로 인라인으로 constexpr되지 않습니다 ...?
whn

4
@아르 자형. std::numeric_limits<double>::is_iec559;이 경우 정적 주장이 필요하지만 충분합니다 . 내가 고백 한 것은 "마스터 헤더"에있는 것입니다. 공식적으로 모든 부동 소수점 유형을 개별적으로 확인해야합니다. 하나가 IEEE754라고해서 모두가 그런 것은 아닙니다.
Bathsheba

2
@DanielSchepler 그렇다면 "숫자"는 무엇입니까? 나는 16 기초를 가진 두 배 숫자가 있다는 것을 몰랐다.
BЈовић

29

M_PI언어 표준이 아닌 경우 "표준"으로 정의됩니다 . POSIX . X / Open System Interfaces 확장을 사용하는 (공식 UNIX 브랜딩에 매우 일반적으로 지원되고 필요함).

C ++ 20에 무엇이 있는지 확신 할 수는 없지만 요청한 후에 아마도 상수 가있을 것입니다 . 이 논문은 2019 년 8 월위원회 초안을 위해 C ++ 20 기능의 마지막 라운드에 병합되었습니다.

특히 std::numbers::pi(유형 double)과 다른 부동 소수점 유형을 원할 경우 사용할 수있는 변수 템플릿이 있습니다 (예 :) std::numbers::pi_v<float>. 상수의 전체 목록은 [numbers.syn] 에서 볼 수 있습니다 .


적합하다고 생각되면 내 편집 내용을 자유롭게 바꾸십시오. 나는 후손을 위해 여기에 새로운 상수의 실제 철자를 추가하고 싶었습니다.
배리

12

도메인 전체에 적용 할 수있는 pi를 정의하는 명백한 유형이 없기 때문에 분명히 좋은 생각은 아닙니다.

파이는 올바르게으로 표현 될 수없는 물론, 무리수, 그래서이다 어떤 C ++ 유형입니다. 따라서 자연스러운 접근 방식은 사용 가능한 가장 큰 부동 소수점 유형으로 정의하는 것입니다. 그러나 가장 큰 표준 부동 소수점 유형의 크기long double 는 C ++ 표준에 의해 정의되지 않으므로 상수 값은 시스템마다 다릅니다. 더 나쁜 것은, 워킹 타입이이 가장 큰 타입이 아닌 프로그램의 경우, pi의 정의는 pi를 사용할 때마다 성능 비용을 부과하기 때문에 부적절한 것입니다.

또한 모든 프로그래머가 pi의 값을 찾고 사용하기에 적합한 상수를 정의하는 것은 사소한 일이므로 수학 헤더에 포함시키는 데 큰 이점을 제공하지 않습니다.


10
C ++ 14는 변수 템플릿을 제공했습니다. 그들이 무엇을위한 것이 아닙니까?
Amomum

21
진심으로위원회 멤버처럼 말하면, 명확한 진로가 제시 되었음에도 불구하고 할 수없는 모든 방법에 대해 이야기하십시오. 놀랍도록 관련이있는 변수 템플릿 예제를 참조하십시오 . 나는 당신의 대답이 나쁘지 않다고 생각하지만 C ++의 미래에 대한 통제권을 매우 결정적인위원회에 넘겨 준 후회에 대한 Bjarne Stroustrup의 영원한 우울증에 도움이되지 않을 것이라고 확신합니다.
whn

4
@snb piHindley-Milner 타입 추론을 가진 언어에서 다형성 상수 를 만드는 것이 분명한 길임을 동의합니다 . 하스켈에서, 우리는 항상 했어 pi :: Floating a => a그 때문에, pi자동으로 값 것이다 3.1415927A의 Float컨텍스트를, 3.141592653589793A의 Double컨텍스트 및 π상징적-계산 컨텍스트한다. 그러나 사람들이 템플릿 매개 변수를 명시 적으로 인스턴스화해야합니까? 특히 고정 long double구현이 대부분의 응용 프로그램에서 동일한 결과를 제공 하는 경우 약간 어색해 보입니다 .
leftaroundabout

2
@leftaroundabout 나는 글쓰기 auto a = pi<float>;가 완전히 훌륭하고, 더 읽기 쉽고 악명 높은 것으로 믿습니다4*atan(1)
Amomum

1
어, 나는 이것을 잘못 클릭하여 downvoted하고 지금은 취소 할 수 없습니다. 죄송합니다. 이것은 개인적으로 사람들이 이미 지적한 이유로 인해 추론에 근본적으로 결함이 있다고 생각하더라도위원회가 추가되지 않은 이유에 대한위원회의 추론에 대한 좋은 설명을 위해 +1이 필요합니다.
기금 모니카의 소송

-1

수정 됨-논란의 여지가 있었으므로 필요한 용어를 제거합니다. 절대 용어가 너무 많습니다.

C ++은 크고 복잡한 언어이므로 표준위원회에는 강력하게 요구 되는 사항 만 포함됩니다 . 부스트와 같은 언어 이외의 표준 라이브러리에는 가능한 한 많이 있습니다.
부스트 :: 수학 :: 상수


29
물론, std::hermite그리고 std::cyl_bessel_i그리고 std::cosh그리고 std::mersenne_twister_engine그리고 std::ranlux48그리고 std::cauchy_distribution그리고 std::assoc_laguerre그리고 std::beta모두가 절대적으로 필요했습니다, 우리 모두는 매일 그것들을 사용합니다!
Amomum

2
위원회 자체조차도 그들이 투표하는 모든 것이 "절대적으로 필요하다"는 생각에 사인 할 수 없었을 것입니다. 그것은 필수가 아니라 언어에 가치를 더하는 것에 관한 입니다. 프로그램을 작성하는 데 표준 라이브러리에는 거의 아무것도 필요하지 않습니다. Turing tarpit, 즉). 파이에 상수를 포함시키는 것의 가치는 논란의 여지가 있지만, 그것이 필요하지 않기 때문에 그것이 거기에 없다는 아이디어는 물을 보유하지 않습니다.
Jeroen Mostert

나에게 불평하지 말고 나는 표준위원회를 인용하고있다. C ++ 11 표준에 얼마나 많은 부스트가 포함되어야하는지에 대한 공개 토론이 오랫동안있었습니다. 이러한 작은 하위 집합이 만들어진 이유는 컴파일러 작성자가 테스트가 얼마나 많이 수행되었는지 불평했기 때문입니다. 따라서 표준에 무언가가 있다면 누군가 표준화해야한다고 생각했기 때문입니다. 이유를 모른다고해서 이유가 없다는 것을 의미하지는 않습니다.
Tiger4Hire

1
@ Tiger4Hire 나는 모든 것에 대한 이유가 있다고 확신합니다. 더 복잡한 것들이 많을 때 pi 상수가 추가되지 않은 이유를 이해할 수 없습니다. 상수는 가변 템플릿으로 작성하기 쉽고 컴파일러 작성자의 많은 테스트가 필요하지 않습니다.
Amomum

@Amomum : 예, pi를 추가하면 큰 승리를위한 작은 오버 헤드처럼 보입니다. 개인적으로 std :: math :: constants 전에 std :: network를보고 싶습니다.
Tiger4Hire
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.