क्या सी ++ 11, 14, 17 या 20 पीआई के लिए एक मानक स्थिर परिचय देता है?


170

सी और सी ++ में संख्या पी के साथ एक बल्कि मूर्खतापूर्ण समस्या है। जहाँ तक मुझे पता M_PIहै math.hकि किसी भी मानक की आवश्यकता नहीं है।

नई सी ++ मानकों ने मानक पुस्तकालय में बहुत सारे जटिल गणित पेश किए - हाइपरबोलिक कार्य, std::hermiteऔर std::cyl_bessel_i, अलग-अलग यादृच्छिक संख्या जनरेटर और इतने पर और आगे।

क्या पीआई के लिए कोई 'नया' मानक निरंतरता में आया? यदि नहीं - क्यों? यह सब जटिल गणित इसके बिना कैसे काम करता है?

मैं सी ++ में पीआई के बारे में इसी तरह के सवालों से अवगत हूं (वे कई साल और मानक पुराने हैं); मैं समस्या की वर्तमान स्थिति जानना चाहूंगा।

मुझे इस बात में भी बहुत दिलचस्पी है कि ओह क्यों सी ++ में अभी भी एक पीआई स्थिर नहीं है, लेकिन बहुत अधिक जटिल गणित है।

UPD: मुझे पता है कि मैं अपने आप को pi को 4 * atan (1) या acos (1) या डबल pi 3.14 के रूप में परिभाषित कर सकता हूं। ज़रूर। लेकिन 2018 में मुझे अभी भी क्यों करना है? बिना pi के मानक गणित कार्य कैसे करते हैं?

UPD2: कोलोन में जुलाई 2019 में C ++ समिति की बैठक के लिए इस यात्रा रिपोर्ट के अनुसार , प्रस्ताव P0631 (गणित स्थिरांक) को C ++ 20 में स्वीकार किया गया था। तो ऐसा लग रहा है कि लंबे समय तक हम मानक पुस्तकालय में नंबर पी लेंगे!


आप पुराने प्रश्नों के अस्तित्व पर ध्यान दें जैसे कि बेस्ट प्लेटफॉर्म इंडिपेंडेंट पीआई कॉन्स्टेंट? । यदि आप चिंता करते हैं कि वे पुराने हैं तो आप हमेशा उनमें से एक को C ++ 17 आदि के आधार पर उत्तर देने के लिए कह सकते हैं ... फिर सभी उत्तर एक ही स्थान पर होंगे। क्यों अभी भी एक अच्छा सवाल है, लेकिन शायद इस पर ध्यान केंद्रित करना चाहिए और मौजूदा तारीखों के लिए क्यों पूछना चाहिए?
शफीक यघमौर

मुझे लगता है कि यह नए जवाब जोड़ने के लायक हो सकता है क्योंकि C ++ 20 ने एक pi निरंतर जोड़ा जहां तक ​​मुझे पता है
Guillaume Racicot

@GuillaumeRacicot मैंने सवाल अपडेट किया। सुनिश्चित नहीं है कि हमें C ++ 20 को संबोधित करना चाहिए क्योंकि यह आधिकारिक तौर पर अभी तक बाहर नहीं है।
अमूमन

@ गिलियूमेरिकॉट: एक जोड़ने में थोड़ी देर हो गई ...
डेविस हेरिंग

जवाबों:


101

C ++ 17 pi को शामिल करना और उसमें शामिल होना भाषा में स्थिर नहीं है, और यह गर्दन में दर्द है।

मैं भाग्यशाली हूं कि मैं बूस्ट का उपयोग करता हूं और वे एक 128 बिट के लिए दशमलव स्थानों की एक पर्याप्त बड़ी संख्या के साथ पाई को परिभाषित करते हैं long double

यदि आप बूस्ट का उपयोग नहीं करते हैं तो इसे स्वयं हार्डकोड करें। त्रिकोणमितीय फ़ंक्शन के साथ इसे परिभाषित करना आकर्षक है, लेकिन यदि आप ऐसा करते हैं तो आप इसे नहीं कर सकते constexpr। त्रिकोणमितीय कार्यों की सटीकता भी (के किसी भी मानक मैं पता करके इसकी गारंटी नहीं है सीएफstd::sqrt), तो वास्तव में आप खतरनाक जमीन वास्तव में इस तरह के एक समारोह पर भरोसा कर रहे हैं।

मेटाप्रोग्रामिंग का उपयोग करके पाई केconstexpr लिए मान प्राप्त करने का एक तरीका है : http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/ देखें


C ++ 20 से कुछ अच्छी खबर। वहाँ है के लिए एक defininition अनुकरणीय । C ++ 20 कुछ गणितीय स्थिरांक जोड़ता है <numbers>। उदाहरण के लिए std::numbers::piएक doubleप्रकार है।

संदर्भ: https://en.cppreference.com/w/cpp/numeric/constants


9
@ लुंडिन: लेकिन यह constexprदुर्भाग्य से नहीं हो सकता , यही कारण है कि मैं कहता हूं "एक ट्रिगर फ़ंक्शन के साथ इसे परिभाषित करना एक दर्द है"
बाथशीबा

9
इससे क्या फर्क पड़ता है? पाई एक स्थिर, परिवर्तन के अधीन या कार्यान्वयन-विशिष्ट कुछ भी नहीं है। बस मूल्य लिखें (एक कास्ट ऑब्जेक्ट में यदि आपको पसंद है) महत्वपूर्ण स्थानों के लिए double(या कुछ हास्यास्पद संख्या यदि आप काल्पनिक वास्तव में लंबे-लंबे डबल्स की परवाह करते हैं)।
आर .. गिटहब स्टॉप हेल्पिंग ICE

10
@ R.. मेरे पास जो समस्या है वह हास्यास्पद है जो अब 20 साल में पूरी तरह से व्यर्थ हो सकती है। (बिल गेट्स के 640k स्प्रिंग्स टू माइंड)। मैं वास्तुकला विकास के साथ बनाए रखने के लिए बूस्ट पर भरोसा करता हूं।
बथशेबा


10
@KonradRudolph: रेंज-रिडक्शन को लागू करने पर एक उच्च-परिशुद्धता पाई मायने रखती है। उदाहरण के लिए, x86 / x87 का आंतरिक पाई स्थिरांक (पूर्ण 64-बिट मंटिसा) छोटे इनपुट के लिए सबसे खराब स्थिति की ओर जाता है fsin, "अंतिम स्थान पर लगभग 1.37 क्विंटल यूनिट्स के निर्देश के लिए, चार बिट्स से कम छोड़ते हुए" । बड़े इनपुट्स के लिए और भी बुरा है, जहां कई बार रेंज-रिडक्शन कम हो जाता है। यह long doubleC ++ के लिए उपयोग किए जाने वाले स्थिरांक के लिए कुछ हद तक स्पर्शरेखा है , लेकिन वैसे भी साफ-सुथरा है।
पीटर कॉर्डेस

31

जैसा कि अन्य लोगों ने कहा है कि std::piयदि कोई सटीक PIमूल्य है तो आप उसका उपयोग कर सकते हैं:

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

यह मानता है कि आपके C ++ कार्यान्वयन से PI का सही-सही गोल मान उत्पन्न होता है acos(-1.0), जो कि सामान्य है लेकिन इसकी गारंटी नहीं है

यह नहीं है constexpr, लेकिन अभ्यास में संकलनकर्ता जैसे gcc और क्लैंग का संकलन समय पर इसका मूल्यांकन करते हैं। constहालांकि यह आशावादी के लिए अच्छा काम करने के लिए घोषित करना महत्वपूर्ण है।


2
यह खतरनाक है क्योंकि acos()फ़ंक्शन में एक अनंत ढलान है x = -1। नतीजतन, यह विधि acos()मूल रूप से एक सटीक -1तर्क के मामले को स्पष्ट रूप से पकड़ने के लिए कार्यान्वयन पर निर्भर करती है, और सीधे सही निरंतर लौटाती है। बेहतर उपयोग करें जैसे 4*atan(1)कि गणितीय रूप से बहुत अधिक मजबूत (अच्छी तरह से व्यवहार किया गया ढलान x = 1और 4 से गुणा हमेशा फ्लोटिंग पॉइंट गणित के साथ सटीक होता है)।
cmaster - मोनिका

1
हमें std::acosनिरंतर अभिव्यक्ति में उपयोग करने की अनुमति नहीं है । क्लैंग इसे त्रुटि के रूप में रिपोर्ट करता है। कृपया ध्यान दें कि यह एक गैर-अनुरूपता विस्तार है और अंततः जीसीसी में तय किया जाना चाहिए। अधिक विवरण के लिए कृपया इस उत्तर को देखें।
बडोला

31

C ++ 20 तक, नहीं, कोई भी मानक निरंतरता का परिचय नहीं देता है जो संख्या pi (π) का प्रतिनिधित्व करेगा । आप अपने कोड में संख्या का अनुमान लगा सकते हैं:

constexpr double pi = 3.14159265358979323846;

अन्य भाषाओं जैसे कि C # को उनके पुस्तकालयों में निरंतर घोषित किया गया है।

अद्यतन: C ++ 20 के साथ शुरू, वास्तव piमें <numbers>हेडर के अंदर एक निरंतर घोषित है । इसके माध्यम से पहुँचा जाता है std::numbers::pi:।


6
आप inlineC ++ 17 + के लिए जोड़ना चाह सकते हैं ।
Deduplicator

8
टा। एक उत्थान है, लेकिन ध्यान दें कि आपकी परिभाषा अभी भी विभिन्न परिभाषाओं के साथ प्लेटफार्मों के साथ अविवेकी की चपेट में है doubledoubleटाइप तय होने के बाद से सी # आसान है। अगर मैं सी ++ मानक समिति पर थे मैं की तरह कुछ का प्रस्ताव करता हूँstd::constants<double>::pi
बतशेबा

11
@Deduplicator के रूप में अच्छी तरह से स्पष्ट रूप से विवश नहीं है ...?
व्हेन

4
@R। पर्याप्त रूप से उचित है, हालांकि आपको std::numeric_limits<double>::is_iec559;उस मामले में स्थिर होना चाहिए । जो, मैं कबूल करता हूं, कि मेरे "मास्टर हेडर" में क्या है। ध्यान दें कि औपचारिक रूप से आपको सभी फ़्लोटिंग पॉइंट प्रकारों को अलग से जांचना होगा। सिर्फ इसलिए कि एक IEEE754 है इसका मतलब यह नहीं है कि वे सभी हैं।
बथशेबा

2
@DanielSchepler तो, उस "संख्या" को क्या माना जाता है? मुझे नहीं पता था कि 16 बेस के साथ डबल नंबर हैं।
B:овиЈ

29

M_PI"एक मानक" द्वारा परिभाषित किया गया है, यदि भाषा मानक नहीं है : एक्स / ओपन सिस्टम इंटरफेस एक्सटेंशन के साथ POSIX (जो आमतौर पर समर्थित है और आधिकारिक UNIX ब्रांडिंग के लिए आवश्यक है)।

यह (अभी भी) निश्चित नहीं है कि C ++ 20 में क्या होगा, लेकिन जब से आपने पूछा: यह शायद ऐसे स्थिरांक होगा । पेपर को C ++ 20 सुविधाओं के अंतिम दौर में विलय कर दिया गया था (अगस्त 2019 में समिति ड्राफ्ट के लिए)।

विशेष रूप से, दोनों std::numbers::piप्रकार के (प्रकार double) होंगे और एक चर टेम्पलेट जिसे आप उपयोग कर सकते हैं यदि आप एक अलग फ्लोटिंग पॉइंट प्रकार चाहते हैं, जैसे std::numbers::pi_v<float>। स्थिरांक की पूरी सूची [नंबरों में देखी जा सकती है । syn]


जैसा कि आप फिट देखते हैं, मेरे संपादन को स्वतंत्र करने के लिए बेझिझक महसूस करें - मैं सिर्फ पोस्टरों के लिए नए स्थिरांक की वास्तविक वर्तनी जोड़ना चाहता था।
बैरी

12

यह स्पष्ट रूप से एक अच्छा विचार नहीं है क्योंकि कोई स्पष्ट प्रकार नहीं है जिसके साथ pi को परिभाषित किया जाए जो सार्वभौमिक रूप से डोमेन पर लागू हो।

पीआई, ज़ाहिर है, एक अपरिमेय संख्या है इसलिए इसे किसी भी सी ++ प्रकार द्वारा सही ढंग से प्रस्तुत नहीं किया जा सकता है । आप तर्क दे सकते हैं कि प्राकृतिक दृष्टिकोण, इसलिए, इसे उपलब्ध सबसे बड़े फ्लोटिंग पॉइंट प्रकार में परिभाषित करना है। हालाँकि, सबसे बड़े मानक फ़्लोटिंग पॉइंट प्रकार long doubleका आकार C ++ मानक द्वारा परिभाषित नहीं किया जाता है, इसलिए स्थिर का मान सिस्टम के बीच भिन्न होगा। इससे भी बदतर, किसी भी कार्यक्रम के लिए जिसमें कामकाजी प्रकार यह सबसे बड़ा प्रकार नहीं था, पीआई की परिभाषा अनुचित होगी क्योंकि यह पीआई के हर उपयोग पर एक प्रदर्शन लागत लगाएगा।

यह किसी भी प्रोग्रामर के लिए पाई के मूल्य का पता लगाने और उपयोग के लिए अपने स्वयं के निरंतर को परिभाषित करने के लिए भी तुच्छ है, इसलिए यह गणित के हेडर में इसे शामिल करने के लिए कोई महान लाभ प्रदान नहीं करता है।


10
C ++ 14 ने हमें वेरिएबल टेम्प्लेट दिए। क्या यह नहीं है कि वे किस लिए हैं?
आमोम

21
एक सच्चे समिति के सदस्य की तरह बात की जाती है, उन सभी तरीकों के बारे में बात की जाती है जो कि स्पष्ट रास्ते के आगे होने के बावजूद नहीं किए जा सकते। आश्चर्यजनक रूप से प्रासंगिक उदाहरण देखें परिवर्तनीय टेम्पलेट । मुझे नहीं लगता कि आपका उत्तर बुरा है, लेकिन मुझे यकीन है कि यह C ++ के भविष्य को एक बहुत ही अनिश्चित समिति को सौंपने के पछतावे पर Bjarne Stroustrup के अनन्त अवसाद में मदद नहीं करेगा।
व्हेन

4
@snb मैं मानता हूं कि piएक बहुरूपी स्थिरांक बनाने से स्पष्ट रास्ता आगे है - हिंडले-मिलनर प्रकार की भाषा में। हास्केल में, हमारे पास हमेशा होता है pi :: Floating a => a, इसलिए यह piस्वचालित रूप 3.1415927से एक Floatसंदर्भ में, 3.141592653589793एक Doubleसंदर्भ में और πएक प्रतीकात्मक-गणना संदर्भ में मूल्य होगा। लेकिन क्या लोग वास्तव में टेम्पलेट पैरामीटर को स्पष्ट रूप से तुरंत करना चाहेंगे? थोड़ा अजीब लगता है, खासकर अगर एक निश्चित long doubleकार्यान्वयन अधिकांश अनुप्रयोगों में समान परिणाम देगा।
19 नवंबर को लेफ्टरेंबाउट

2
@leftaroundabout मेरा मानना ​​है कि लेखन auto a = pi<float>;पूरी तरह से ठीक है, निश्चित रूप से अधिक पठनीय है तो कुख्यात4*atan(1)
अमूमन

1
उह, मैंने इसे मिसकॉल द्वारा डाउनवोट किया और अब मैं इसे पूर्ववत नहीं कर सकता। माफ़ करना। यह समिति के तर्क के एक बहुत अच्छे स्पष्टीकरण के लिए एक योग्य है कि इसे क्यों नहीं जोड़ा गया है, भले ही मुझे व्यक्तिगत रूप से लगता है कि तर्क मौलिक रूप से उन कारणों के लिए त्रुटिपूर्ण है जो लोग पहले ही बता चुके हैं।
निधि मोनिका का मुकदमा

-1

संपादित - आवश्यक शब्द को हटाने के लिए, क्योंकि यह विवादास्पद साबित हुआ। यह बहुत अधिक निरपेक्ष शब्द है।

सी ++ एक बड़ी और जटिल भाषा है, इस कारण से मानक समिति में केवल उन चीजों को शामिल किया जाता है जिनकी दृढ़ता से आवश्यकता होती है । जितना संभव हो उतना गैर-भाषा मानक पुस्तकालयों के लिए छोड़ दिया जाता है ... बूस्ट की तरह।
को बढ़ावा देने :: गणित :: स्थिरांक


29
बेशक, std::hermiteऔर std::cyl_bessel_iऔर std::coshऔर std::mersenne_twister_engineऔर std::ranlux48और std::cauchy_distributionऔर std::assoc_laguerreऔर std::betaसब बिल्कुल जरूरी थे, हम सब उन्हें हर दिन का उपयोग करें!
अमूमन

2
मुझे पूरा यकीन है कि आप इस समिति को इस विचार पर हस्ताक्षर करने के लिए भी नहीं मिल सकते थे कि वे जो भी वोट देते हैं वह "बिल्कुल आवश्यक" है। यह आवश्यकता के बारे में नहीं है, लेकिन भाषा के लिए मूल्य जोड़ने के बारे में है - मानक पुस्तकालय में लगभग कुछ भी प्रोग्राम लिखने के लिए आवश्यक नहीं है, और इस मामले के लिए अधिकांश मूल भाषा को भी बाहर फेंक दिया जा सकता है (यदि आप एक में काम करने का मन नहीं रखते हैं ट्यूरिंग टारपीट, वह है)। पाई के लिए एक स्थिरांक को शामिल किए जाने के मूल्य पर बहस की जा सकती है, लेकिन यह विचार कि यह वहां नहीं है क्योंकि यह जरूरी नहीं है कि इसमें पानी नहीं है।
जेरोइन मोस्टर्ट

मुझे शिकायत मत करो, मैं सिर्फ मानक समिति को उद्धृत कर रहा हूं। C ++ 11 मानक में कितना बढ़ावा शामिल होना चाहिए, इस बारे में लंबे समय से खुली चर्चा थी। इस तरह के एक छोटे उपसमुच्चय ने इसका कारण बना दिया क्योंकि संकलक लेखकों ने शिकायत की कि परीक्षण कितना शामिल था। इसलिए, अगर कुछ मानकों में है, तो यह वहां है क्योंकि किसी ने इसे मानकीकृत करना आवश्यक समझा। सिर्फ इसलिए कि आप नहीं जानते, इसका मतलब यह नहीं है कि कोई कारण नहीं था।
Tiger4Hire

1
@ Tiger4Hire मुझे यकीन है कि सब कुछ के लिए कारण है, मैं अभी यह नहीं समझ सकता कि पीआई के लिए निरंतर क्यों नहीं जोड़ा गया जब बहुत अधिक वास्तविक चीजें थीं। लगातार परिवर्तनशील टेम्प्लेट के साथ लिखना आसान है और संकलक लेखकों से बहुत अधिक परीक्षण की आवश्यकता नहीं होगी।
अमूमन

@Amomum: हाँ, पी को जोड़ना एक बड़ी जीत के लिए एक छोटे उपरि की तरह लगता है। मन, व्यक्तिगत रूप से मैं std :: नेटवर्क से पहले std :: math :: constants देखना पसंद करूंगा।
Tiger4Hire
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.