วิธีใช้ค่าคงที่ PI ใน C ++


476

ฉันต้องการใช้ค่าคงที่ PI และฟังก์ชันตรีโกณมิติในบางโปรแกรม C ++ include <math.h>ฉันได้รับฟังก์ชันตรีโกณมิติกับ อย่างไรก็ตามดูเหมือนจะไม่มีคำจำกัดความของ PI ในไฟล์ส่วนหัวนี้

ฉันจะรับ PI โดยไม่ต้องกำหนดด้วยตนเองได้อย่างไร


3
@tiwo คุณกำลังขอให้สิ่งที่แตกต่างระหว่าง3.14, 3.141592และatan(1) * 4?
Nikola Malešević

21
ในฐานะที่เป็นบันทึกด้านข้าง, cmath ควรใช้ใน C ++ แทน math.h ซึ่งใช้สำหรับ C.
juzzlin

4
เกี่ยวข้องอย่างหลวม ๆ : ดูcise.ufl.edu/~manuel/obfuscate/pi.cเกี่ยวกับวิธีการคำนวณมูลค่าของ PI โดยตรงจากคำจำกัดความ
lorro

คำตอบ:


537

ในบางแพลตฟอร์ม (โดยเฉพาะอย่างยิ่งเก่ากว่า) (ดูความคิดเห็นด้านล่าง) คุณอาจจำเป็นต้อง

#define _USE_MATH_DEFINES

จากนั้นรวมไฟล์ส่วนหัวที่จำเป็น:

#include <math.h>

และคุณค่าของ pi สามารถเข้าถึงได้ผ่าน:

M_PI

ใน my 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.
 */

อย่างไรก็ตาม:

  1. บนแพลตฟอร์มที่ใหม่กว่า (อย่างน้อยใน Ubuntu 64 บิต 14.04) ฉันไม่จำเป็นต้องกำหนด _USE_MATH_DEFINES

  2. บน (ล่าสุด) แพลตฟอร์ม Linux มีlong doubleค่าที่จัดเตรียมไว้ให้เป็นส่วนขยาย GNU ด้วย:

    # define M_PIl          3.141592653589793238462643383279502884L /* pi */

51
#define _USE_MATH_DEFINESตามด้วย#include <math.h>นิยามM_PIใน visual c ++ ขอบคุณ
Etan

3
ทำงานร่วมกับส่วนหัว cygwin เช่นกัน
Rob

24
คุณสามารถรวมแทนcmath math.h
Richard J. Ross III

10
แม้หลังจากที่กำหนด_USE_MATH_DEFINESถ้า GCC บ่นว่าเพราะ__STRICT_ANSI__ถูกกำหนด (บางทีคุณอาจผ่าน-pedanticหรือ-std=c++11) ซึ่งไม่อนุญาตให้M_PIมีการกำหนดไว้จึง undefine -D__STRICT_ANSI__มันด้วย เมื่อกำหนดได้ด้วยตัวเองเพราะมันของ C ++ constexpr auto M_PI = 3.14159265358979323846;แทนแมโครที่คุณควร
ตำนาน 2k

1
ตั้งแต่ปีพ. ศ. 2561 คำตอบควรได้รับการปรับปรุงอย่างแน่นอนเพื่อใช้ <cmath> แทนที่จะเป็น <math.h>
jaskmar

170

สามารถคำนวณ Pi ได้atan(1)*4ดังนี้ คุณสามารถคำนวณมูลค่าด้วยวิธีนี้และแคช


78
สำหรับผู้ใช้ c ++ 11:constexpr double pi() { return std::atan(1)*4; }
matiu

41
-1: ใช้ได้เฉพาะถ้าatan(1)*4 == 3.141592653589793238462643383279502884(พูดโดยประมาณ) ฉันจะไม่เดิมพันกับมัน เป็นปกติและใช้ตัวอักษรดิบเพื่อกำหนดค่าคงที่ ทำไมสูญเสียความแม่นยำเมื่อคุณไม่ต้องการ?
Thomas Eding

29
atan2(0, -1);หนึ่งสามารถหลีกเลี่ยงการดำเนินการคูณด้วย
ตำนาน 2k

44
@matiu ไม่atan constexpr
R. Martinho Fernandes

45
ลองแทนจำเป็นที่จะต้องไม่มีacos(-1) atan2
user541686

113

นอกจากนี้คุณยังสามารถใช้การเพิ่มซึ่งกำหนดค่าคงที่ทางคณิตศาสตร์ที่สำคัญด้วยความแม่นยำสูงสุดสำหรับประเภทที่ร้องขอ (เช่น float vs double)

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

ตรวจสอบเอกสารประกอบการส่งเสริมสำหรับตัวอย่างเพิ่มเติม


184
Boost: เพิ่มความซับซ้อนที่ไม่จำเป็นของ C ++ ตั้งแต่ปี 1999!
Dan Molding

47
ลวงและเป็นจริงบางส่วน ในการเพิ่มมืออื่น ๆ จะมีประโยชน์เปรอะเปื้อนในบางครั้ง ...
BuschnicK

59
@DanMoulding: อืม C เป็นภาษาอื่นที่คุณรู้จักหรือไม่? เพราะภาษาอื่น ๆ ทั้งหมดที่ฉันรู้จักยกเว้น C มีห้องสมุดมาตรฐานซึ่งมีขนาดใหญ่กว่า C ++ '(เช่น Python, Haskell, C #, PHP, Delphi, Erlang, Java, ...... ) จากประสบการณ์ส่วนตัวว่า elitist not gonna use libs-opinion เป็นศัตรูพืชและอาจเป็นสาเหตุอันดับหนึ่งสำหรับซอฟต์แวร์ที่ไม่ดีที่เขียนใน C ++
เซบาสเตียนมัค

11
@Gracchus: ใช่แล้ว C ++ ที่ไม่มีไลบรารี่ (หรือไม่มีไลบรารี่ C ++ 11) คือเท่าที่ฉันชอบภาษานั้นและเท่าที่ฉันต้องการโค้ดทุกอย่างด้วยตัวเอง
Sebastian Mach

14
ผมเชื่อว่าเขากล่าวว่าความซับซ้อนไม่ได้ขนาด อ้างถึง a) 3 เนมสเปซที่ซ้อนกันและ b) นิยาม pi เป็นฟังก์ชันเทมเพลตแทนที่จะเป็นแค่ค่าคงที่ปกติ
Timmmm

83

รับจากหน่วย FPU บนชิปแทน:

double get_PI()
{
    double pi;
    __asm
    {
        fldpi
        fstp pi
    }
    return pi;
}

double PI = get_PI();

40
:-) อาจไม่ใช่แพลตฟอร์มที่เป็นอิสระ แต่เป็นโซลูชันที่แปลกใหม่เพิ่มเติม!
Etan

3
ฉันชอบที่คุณออกมานอกกรอบที่นี่;)
VivienLeger

1
ฉันรักคำตอบนี้ มันจะมีประโยชน์อย่างยิ่งเมื่อกำหนดเป้าหมายแพลตฟอร์ม x86 ที่มีขนาดเล็กจนถึงปลายปีซึ่งคอมไพเลอร์ที่ปรับให้เหมาะสมไม่ได้มีส่วนเกี่ยวข้องมากเท่ากับสมัยใหม่ ขอบคุณสำหรับเฮนริกนี้!
Matt

49

ฉันอยากจะแนะนำเพียงพิมพ์ใน pi เพื่อความแม่นยำที่คุณต้องการ สิ่งนี้จะเป็นการเพิ่มเวลาในการคำนวณของคุณและจะสามารถพกพาได้โดยไม่ต้องใช้ส่วนหัวหรือ #defines การคำนวณ acos หรือ atan มักจะแพงกว่าการใช้ค่าที่คำนวณไว้ล่วงหน้า

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

28
นี่เป็นตัวอย่างที่ดีว่าทำไมเราไม่ควรใช้วิธีนี้เราคนทำผิดพลาดปัดเศษคัดลอกและวาง ฯลฯ ฉันคิดว่าการใช้ M_PI เป็นวิธีที่เหมาะสม
nacho4d

10
หากมีการทำเช่นนี้ใน C ++ 11 ทำให้ constconstexpr
ตำนาน 2k

3
@ nacho4d ฉันก็ชอบ M_PI ด้วยถ้ามี แต่ไม่ใช่ทุกระบบที่รองรับ POSIX ฉันคิดว่าวิธีนี้ดีกว่าวิธี 4 * atan (1) สำหรับกรณีที่ไม่มี M_PI
m24p

2
"การคำนวณ acos หรือ atan นั้นแพงกว่าเสมอ" ไม่เป็นความจริง คอมไพเลอร์การปรับให้เหมาะสมที่ทันสมัยทุกคนรู้ทุกอย่างเกี่ยวกับฟังก์ชั่นคณิตศาสตร์มาตรฐานและสามารถเผยแพร่อย่างต่อเนื่องผ่านพวกเขา ดูเช่นgoo.gl/BvdJyr
Nemo

2
@Nemo เคาน์เตอร์เช่น: godbolt.org/g/DsAernในฐานะที่ได้รับการกล่าวว่าที่อื่นก็จะปรากฏขึ้นเฉพาะ GCC constexprไม่นี้ในขณะนี้และที่มีแนวโน้มเพราะมันได้ประกาศฟังก์ชั่นพื้นฐานทางคณิตศาสตร์เป็น
Parker Coates

47

แทนที่จะเขียน

#define _USE_MATH_DEFINES

ฉันอยากจะแนะนำให้ใช้-D_USE_MATH_DEFINESหรือ/D_USE_MATH_DEFINESขึ้นอยู่กับคอมไพเลอร์ของคุณ

วิธีนี้คุณจะมั่นใจได้ว่าแม้ในกรณีที่มีใครบางคนรวมถึงส่วนหัวก่อนที่คุณจะทำ (และไม่มี #define) คุณจะยังคงมีค่าคงที่แทนที่จะเป็นข้อผิดพลาดของคอมไพเลอร์ที่คลุมเครือ


เคล็ดลับดี หาก "คุณ" เป็นหน่วยการรวบรวมแน่นอนว่าคุณสามารถมั่นใจได้ว่ามีการกำหนดแมโครก่อนที่จะมีสิ่งใดรวมอยู่ด้วย แต่ถ้า "คุณ" เป็นไฟล์ส่วนหัวคุณจะไม่สามารถควบคุมได้
Steve Jessop

3
ในความเป็นจริงแม้ว่า "คุณ" เป็นหน่วยการรวบรวม ... ขึ้นอยู่กับการสั่งซื้อของส่วนหัวเป็นเส้นทางที่สั้นที่สุดไปสู่ฝันร้ายการบำรุงรักษา ...
Matthieu M.

1
คุณไม่จำเป็นต้องพึ่งพาการสั่งซื้อส่วนหัว ไม่สำคัญว่าส่วนหัวจะรวมกันหรือไม่โดยที่คุณทำ #define ก่อนที่คุณจะรวมสิ่งใด ๆ เลย (อย่างน้อยก็สมมติว่าไม่มี #undefs อยู่) เช่นเดียวกับ NDEBUG
Steve Jessop

1
ปัญหาที่พบบ่อยมากในโครงการคือถ้าคุณกำลังคอมไพล์ด้วย Visual Studio คุณไม่ทราบว่าคอมไพเลอร์จะผ่านไฟล์ของคุณอย่างไรดังนั้นถ้าคุณใช้<cmath>ในสถานที่ต่าง ๆ มันจะกลายเป็นความเจ็บปวดครั้งใหญ่ ถ้ามันถูกรวมอยู่ในห้องสมุดอื่นคุณจะรวม) มันคงจะดีกว่ามากถ้าพวกเขาเอาส่วนนั้นออกมานอกยามหัว แต่ก็ไม่สามารถทำอะไรได้มากในตอนนี้ คอมไพเลอร์คำสั่งทำงานได้ค่อนข้างดีแน่นอน
meneldal

40

เนื่องจากไลบรารีมาตรฐานอย่างเป็นทางการไม่ได้กำหนดค่าคงที่ PI คุณจะต้องกำหนดด้วยตนเอง ดังนั้นคำตอบสำหรับคำถามของคุณ "ฉันจะรับ PI ได้อย่างไรโดยไม่ต้องกำหนดด้วยตนเอง" คือ "คุณไม่ - หรือใช้ส่วนขยายเฉพาะคอมไพเลอร์" หากคุณไม่กังวลเกี่ยวกับการพกพาคุณสามารถตรวจสอบคู่มือคอมไพเลอร์ของคุณสำหรับสิ่งนี้

C ++ อนุญาตให้คุณเขียน

const double PI = std::atan(1.0)*4;

แต่การเริ่มต้นของค่าคงที่นี้ไม่รับประกันว่าจะคงที่ คอมไพเลอร์ G ++ อย่างไรก็ตามจัดการฟังก์ชันคณิตศาสตร์เหล่านั้นเป็นอินทรินและสามารถคำนวณนิพจน์คงที่นี้ในเวลาคอมไพล์


6
ฉันมักจะใช้ acos (-1) ตามที่คุณพูดพวกเขาจะรวบรวมการประเมินเวลา เมื่อฉันทดสอบ M_PI, acos (-1) และ atan (1) * 4 ฉันมีค่าเหมือนกัน
คาห์

2
วิธีดั้งเดิมคือการใช้4*atan(1.): ใช้งานatanง่ายและคูณด้วย 4 เป็นการดำเนินการที่แน่นอน แน่นอนคอมไพเลอร์ที่ทันสมัยพับ (มีจุดมุ่งหมายที่จะพับ) ค่าคงที่ทั้งหมดที่มีความแม่นยำที่จำเป็นและก็สมบูรณ์เหมาะสมที่จะใช้acos(-1)หรือแม้กระทั่งstd::abs(std::arg(std::complex<double>(-1.,0.)))ซึ่งเป็นสิ่งที่ตรงกันข้ามของสูตรออยเลอร์และทำให้มากขึ้นสกอร์ที่ชื่นชอบกว่าดูเหมือนว่า (ฉันได้เพิ่มabsเพราะผม Don' จำไม่ได้ว่าระนาบเชิงซ้อนถูกตัดหรือว่ามันถูกนิยามไว้อย่างไร)
tobi_s

แค่ไม่มีใครคิดว่าคุณจริงจัง (อีกครั้ง -_- ') นี่คือทางออกที่น่ากลัว การดำเนินการ atan ไม่ได้กำหนดโดยมาตรฐานหมายถึงการดำเนินการและอาจขึ้นอยู่กับ hw ซึ่งหมายความว่าตัวเลขอาจแย่มากซึ่งหมายความว่าคุณอาจจะดีกว่าถ้าใช้ 3.14 โดยทั่วไป ยิ่งไปกว่านั้นมันอาจจะช้าแม้ในกรณีพิเศษ
midjji

32

จากหน้าPosix ของ math.h :

   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

3
คำตอบที่ดี แต่ลิงค์ตายไปแล้ว ฉันแนะนำอันนี้แทน
Abderrahim Kitouni

30

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 “ ส่วนหัว” [ส่วนหัว] ในตาราง [แท็บ: 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


27

Standard C ++ ไม่มีค่าคงที่สำหรับ PI

คอมไพเลอร์ C ++ จำนวนมากกำหนดM_PIในcmath(หรือในmath.hสำหรับ C) เป็นส่วนขยายที่ไม่ได้มาตรฐาน คุณอาจต้องทำ#define _USE_MATH_DEFINESก่อนที่จะเห็น


18

ฉันจะทำ

template<typename T>
T const pi = std::acos(-T(1));

หรือ

template<typename T>
T const pi = std::arg(-std::log(T(2)));

ฉันจะไม่ พิมพ์ในπความแม่นยำที่คุณต้องการ นั่นคือสิ่งที่ควรจะหมายถึงอะไร ความแม่นยำที่คุณต้องการคือความแม่นยำของแต่เรารู้อะไรเกี่ยวกับTT

คุณอาจพูดว่า: คุณกำลังพูดเรื่องอะไร Tจะเป็นfloat, หรือdouble long doubleดังนั้นเพียงพิมพ์ความแม่นยำของlong doubleเช่น

template<typename T>
T const pi = static_cast<T>(/* long double precision π */);

แต่จริงๆคุณรู้ว่ามีจะไม่เป็นแบบใหม่จุดที่ลอยอยู่ในมาตรฐานในอนาคตที่มีความแม่นยำที่สูงยิ่งขึ้นกว่าlong double? คุณทำไม่ได้

และนั่นเป็นเหตุผลที่ทางออกแรกนั้นสวยงาม คุณสามารถมั่นใจได้ว่ามาตรฐานจะทำงานเกินฟังก์ชันตรีโกณมิติสำหรับประเภทใหม่

และโปรดอย่าพูดว่าการประเมินฟังก์ชั่นตรีโกณมิติเมื่อเริ่มต้นนั้นเป็นโทษประสิทธิภาพ


1
โปรดทราบว่าทั้งหมดarg(log(x)) == π 0 < x < 1
0xbadf00d

นี่เป็นความคิดที่แย่มาก ใช้เท็มเพลตที่โอเวอร์โหลดเทมเพลตต่อประเภทซึ่งเป็นวิธีที่คุณจะได้รับข้อผิดพลาดในการคอมไพล์เพื่อบังคับให้คุณกำหนดหากประเภทใหม่ปรากฏขึ้น โดยทั่วไปแล้วมันแย่มากเพราะประเภทของตรีโกณมิติไม่ได้ จำกัด อยู่ที่ประเภทจุดลอย ดังนั้นเพลิดเพลินไปกับความผิดพลาด atan (1) ... มาตรฐานไม่รับประกันว่าฟังก์ชันตรีโกณมิติคำนวณค่าตรีโกณมิติที่แท้จริงของพวกเขาเพื่อความถูกต้องของประเภท โดยทั่วไปแล้วพวกเขาทำไม่ได้และมันแย่ลงด้วยเช่น fastmath และไม่ดีโดยเฉพาะอย่างยิ่งสำหรับค่าพิเศษ
midjji

10

ฉันใช้สิ่งต่อไปนี้ในส่วนหัวร่วมหนึ่งในโครงการที่ครอบคลุมทุกฐาน:

#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>ค่าคงที่ถ้าคุณรวม ไม่จำเป็นต้องเพิ่ม `#define _USE_MATH_DEFINES ซึ่งจำเป็นสำหรับ VC ++ เท่านั้น

x86 GCC 4.4+
ARM GCC 4.5+
x86 Clang 3.0+

ผู้ลงคะแนนสามารถแสดงความคิดเห็นในสิ่งที่ผิดกับคำตอบนี้ได้ นี่คือการวิจัยและทดสอบอย่างดีและมีการใช้งานในระบบจริง ฉันอยากปรับปรุงถ้ามีอะไรผิดปกติ
Shital Shah

1
FYI, คอมไพเลอร์ Borland C ++ ยังนิยามM_PIโดยไม่จำเป็น_USE_MATH_DEFINES
Remy Lebeau

8

โดยทั่วไปฉันชอบกำหนดของตัวเอง: const double PI = 2*acos(0.0);เนื่องจากการใช้งานไม่ได้มีให้สำหรับคุณ

คำถามที่ว่าฟังก์ชั่นนี้ถูกเรียกเมื่อรันไทม์หรือเป็น static'ed ในเวลาคอมไพล์มักจะไม่เป็นปัญหาเพราะมันเกิดขึ้นเพียงครั้งเดียวเท่านั้น


8
acos (-1) ก็เป็น pi
Roderick Taylor

3
บ่อยครั้งที่คำสั่ง CPU และ / หรือเวลาแฝงน้อยลงในการโหลดตัวถูกดำเนินการทันทีกว่าอ่านตัวถูกดำเนินการจากตำแหน่งหน่วยความจำ นอกจากนี้เฉพาะการแสดงออกที่รู้จักกันในเวลารวบรวมสามารถคำนวณล่วงหน้า (ฉันหมายถึงdouble x = pi * 1.5;และไม่ชอบ) ถ้าคุณตั้งใจจะใช้ PI ในคณิตศาสตร์ที่มีการวนซ้ำในวงแคบคุณควรตรวจสอบให้แน่ใจว่าคอมไพเลอร์เป็นที่รู้จักกันดี
Eugene Ryabtsev

7

ฉันเพิ่งเจอบทความนี้โดยDanny Kalevซึ่งมีเคล็ดลับที่ดีสำหรับ C ++ 14 ขึ้นไป

template<typename T>
constexpr T pi = T(3.1415926535897932385);

ฉันคิดว่ามันค่อนข้างเจ๋ง (แม้ว่าฉันจะใช้ PI ที่มีความแม่นยำสูงที่สุดเท่าที่จะทำได้) โดยเฉพาะอย่างยิ่งเพราะเทมเพลตสามารถใช้งานได้ตามประเภท

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>

4

ค่าเช่น M_PI, M_PI_2, M_PI_4 และอื่น ๆ ไม่ใช่ C ++ มาตรฐานดังนั้น constexpr ดูเหมือนจะเป็นทางออกที่ดีกว่า การแสดงออกของ const ที่แตกต่างกันสามารถกำหนดสูตรที่คำนวณ pi เดียวกันและมันเกี่ยวข้องกับฉันว่าพวกเขา (ทั้งหมด) ให้ความแม่นยำเต็มที่กับฉันหรือไม่ มาตรฐาน 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;
}

2
ดีมาก. อาจจำเป็นต้องมี "l" หรือ "L" ที่ท้ายหมายเลขนั้น ฉันได้รับคำเตือนที่แคบลงจากคอมไพเลอร์ gcc ของฉันบน linux
Grant Rostig

2

บน Windows (Cygwin + g ++) ฉันได้พบมันจำเป็นที่จะต้องเพิ่มธง-D_XOPEN_SOURCE=500สำหรับ preprocessor ในการประมวลผลคำจำกัดความของในM_PImath.h


2
นี่ไม่ใช่คำตอบ แต่เป็นความคิดเห็นต่อคำตอบของ fritzone
0xbadf00d

2
@ 0xbadf00d: มันเป็นคำตอบแบบสแตนด์อโลนที่ให้ขั้นตอนที่จำเป็นในM_PIการทำงานบนแพลตฟอร์มเฉพาะ นั่นไม่ใช่ความเห็นเกี่ยวกับคำตอบสำหรับแพลตฟอร์มอื่น ๆ อีกต่อไปว่าคำตอบสำหรับแพลตฟอร์มอื่นคือความคิดเห็นในอันนี้
Ben Voigt

2

C ++ 14 ให้คุณทำ static constexpr auto pi = acos(-1);


9
std::acosconstexprไม่ได้เป็น ดังนั้นรหัสของคุณจะไม่รวบรวม
0xbadf00d

@ 0xbadf00d ฉันรวบรวมมันด้วย g ++
Willy Goat

12
@WillyGoat: ดังนั้น g ++ จะผิดเพราะacosไม่ได้constexprอยู่ใน C ++ 14 และไม่ได้เสนอให้เป็นconstexprแม้แต่ใน C ++ 17
Ben Voigt

@BenVoigt จะมีฟังก์ชั่นทางคณิตศาสตร์ใด ๆ ที่constexpr? ไม่ชัดเจน: stackoverflow.com/questions/17347935/constexpr-math-functions
wcochran

1
@wcochran: มีฟังก์ชั่นคณิตศาสตร์ใหม่ ๆ มากมายconstexprให้ดูตัวอย่าง ( github.com/kthohr/gcem ) แต่ไม่เข้ากันได้กับฟังก์ชั่น C ที่มีชื่อเดียวกันดังนั้นจึงไม่สามารถใช้ชื่อเดิมได้
Ben Voigt

2

โซลูชั่นที่หรูหรา ฉันสงสัยว่าความแม่นยำของฟังก์ชันตรีโกณมิติจะเท่ากับความแม่นยำของประเภทแม้ว่า สำหรับผู้ที่ต้องการเขียนค่าคงที่สิ่งนี้ใช้ได้กับ g ++: -

template<class T>
class X {
public:
            static constexpr T PI = (T) 3.14159265358979323846264338327950288419\
71693993751058209749445923078164062862089986280348253421170679821480865132823066\
47093844609550582231725359408128481117450284102701938521105559644622948954930381\
964428810975665933446128475648233786783165271201909145648566923460;
...
}

ความแม่นยำทศนิยม 256 หลักควรเพียงพอสำหรับการพิมพ์ Double Long Long Long ในอนาคต หากเข้าชมมากขึ้นจะต้องhttps://www.piday.org/million/



1

คุณสามารถทำได้:

#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

หากM_PIถูกกำหนดไว้แล้วในการcmathนี้จะไม่ทำอะไรอย่างอื่นมากกว่า cmathได้แก่ หากM_PIไม่ได้กำหนดไว้ (ซึ่งเป็นกรณีตัวอย่างใน Visual Studio) จะเป็นการกำหนด ในทั้งสองกรณีคุณสามารถใช้M_PIเพื่อรับค่า pi

ค่าของ pi นี้มาจาก qmath.h ของ Qt Creator


1

คุณสามารถใช้สิ่งต่อไปนี้

#define _USE_MATH_DEFINES // for C++
#include <cmath>

#define _USE_MATH_DEFINES // for C
#include <math.h>

ค่าคงที่ทางคณิตศาสตร์ไม่ได้ถูกกำหนดใน Standard C / C ++ จะใช้พวกเขาครั้งแรกที่คุณจะต้องกำหนด_USE_MATH_DEFINESแล้วรวมหรือcmathmath.h

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.