C / C ++ में न्यूनतम डबल मान


92

क्या C (++) प्रोग्राम में सबसे छोटे ऋणात्मक मान (जैसे नकारात्मक अनंत का उपयोग करने के लिए) का प्रतिनिधित्व करने के लिए एक मानक और / या पोर्टेबल तरीका है?

फ्लोट में DBL_MIN.h सबसे छोटी पॉजिटिव संख्या है।


4
मैं -DBL_MAX के लिए जाऊंगा, लेकिन मुझे यकीन है कि कुछ तकनीकी कारण है कि ऐसा क्यों नहीं है :-)

4
@ नहीं, नहीं, ऐसा नहीं है, यह 2 पूरक पूर्णांकों की तरह नहीं है
फोरट्रान

मैंने अभी तक मानक में कुछ भी नहीं देखा है यह कहने के लिए कि फ्लोटिंग पॉइंट प्रकारों की सीमा शून्य के आसपास सममित होनी चाहिए। लेकिन लिमिट्स में स्थिरांक .h और <सीमाएं> यह सुझाव देती हैं कि C और C ++ मानक दोनों ही एक तरह की अपेक्षा है।
स्टीव जेसोप

4
वास्तव में फ्लोट में DBL_MIN.h सबसे छोटी पॉजिटिव नॉर्मलाइज्ड संख्या है। ऐसी संख्याएँ हैं जो और भी छोटी हैं।
fdermishin

1
@fortran: IEEE 754 FP एक सांकेतिक बिट का उपयोग करता है, और निश्चित रूप से इन दिनों सबसे अधिक FP हार्डवेयर IEEE 754 है। लेकिन C और C ++ गैर-IEEE 754 FP हार्डवेयर का समर्थन करते हैं, इसलिए यह प्रश्न खुला है कि क्या भाषा गारंटी देती है कि -DBL_MAX न्यूनतम प्रतिनिधित्व योग्य मूल्य के बराबर होना चाहिए।
j_random_hacker

जवाबों:


134

-DBL_MAX एएनएसआई सी में , जिसे फ्लोट में परिभाषित किया गया है।


यह सबसे मानक और पोर्टेबल लगता है
विल

यहाँ मेरे -1 के लिए स्पष्टीकरण दिया गया है: कौन या क्या कहता है कि -DBL_MAX को C या C ++ भाषा द्वारा प्रतिनिधित्व योग्य होने की गारंटी है, अकेले न्यूनतम प्रतिनिधित्व योग्य मान दें? तथ्य यह है कि अधिकांश एफपी हार्डवेयर IEEE 754-अनुरूप है, और यह इस प्रतिनिधित्व का उपयोग करता है, इसका मतलब यह नहीं है -DBL_MAX किसी भी मानक-अनुरूप सी प्लेटफ़ॉर्म पर काम करने की गारंटी है।
j_random_hacker

@j_random_hacker: फोरट्रान का जवाब 'नीचे' देखें।
जॉनटोर्टुगो

3
@j_random_hacker यह एक बहुत अच्छा बिंदु है, लेकिन सी मानक को -DBL_MAXबिल्कुल प्रतिनिधित्व करने की आवश्यकता है, इसलिए यदि एफपी हार्डवेयर इसके लिए सक्षम नहीं है, तो कार्यान्वयन को बस इसके चारों ओर काम करना होगा। 5.2.4.2.2 में फ्लोटिंग-पॉइंट मॉडल देखें। फ़्लोटिंग प्रकार के लक्षण <फ़्लोट.एच> सी 2 के सी 99 (तब से कहीं और ले जाया जा सकता है)।

2
@j_random_hacker हां, लेकिन P2 निर्दिष्ट करता है e_min और e_max साइन बिट से स्वतंत्र हैं, इसलिए DBL_MAXवास्तव में (1 - b ^ −p) b ^ e_max है, जो वास्तव में प्रतिनिधित्व योग्य है, सबसे नकारात्मक परिमित मूल्य बिल्कुल है - (1 - b ^ Andp) b ^ e_max, और चूँकि ऐसा बिल्कुल होता है -DBL_MAX, इसलिए DBL_MAXकिसी भी गोलाई में त्रुटियों का परिचय नहीं दिया जा सकता है ।

70

फ़्लोटिंग पॉइंट नंबर (IEEE 754) सममित हैं, इसलिए यदि आप सबसे बड़ा मान ( DBL_MAXया numeric_limits<double>::max()) का प्रतिनिधित्व कर सकते हैं, तो बस एक ऋण चिह्न का संकेत दें।

और फिर अच्छा तरीका है:

double f;
(*((long long*)&f))= ~(1LL<<52);

6
+1 फ़्लोटिंग पॉइंट नंबरों की समरूपता को इंगित करने के लिए :)
एंड्रयू हरे

4
क्या सी / सी + + कार्यान्वयन के बारे में जो IEEE 754 फ़्लोट का उपयोग नहीं करते हैं?
स्टीव जेसोप

1
Gcc का मैनुअल फॉर -फॉस्ट-मैथ कहता है "सेट्स -फनो-मैथ-इरनो, -फुनसफे-मैथ-ऑप्टिमाइज़ेशन, -फिन्टे-मैथ-ओनली, -फनो-राउंडिंग-मैथ, -फैन-सिग्नलिंग-नन्स और -fcx-limited- रेंज यह विकल्प किसी भी -O विकल्प द्वारा चालू नहीं किया जाता है क्योंकि इससे प्रोग्राम के लिए गलत आउटपुट हो सकता है जो गणित के कार्यों के लिए IEEE या ISO नियमों / विशिष्टताओं के सटीक कार्यान्वयन पर निर्भर करता है। हालांकि, इससे उन कार्यक्रमों के लिए तेज़ कोड प्राप्त हो सकता है। इन विशिष्टताओं की गारंटी की आवश्यकता नहीं है। " फास्ट गणित एक सामान्य सेटिंग है, और इंटेल आईसीसी उदाहरण के लिए इसे करने के लिए चूक। सब सब, निश्चित नहीं कि मेरे लिए इसका क्या मतलब है :-)
विल

4
इसका मतलब है कि कार्यान्वयन IEEE 754 अंकगणित का उपयोग नहीं करते हैं, लेकिन निष्पक्ष होने के लिए वे विकल्प अभी भी IEEE प्रतिनिधित्व का उपयोग करते हैं। आपको गैर-IEEE प्रतिनिधित्व का उपयोग करके कुछ एमुलेशन लाइब्रेरी मिल सकती हैं, क्योंकि सभी प्रोसेसरों में एक देशी फ्लोट प्रारूप नहीं होता है (हालांकि वे एक सी एबीआई प्रकाशित कर सकते हैं जिसमें निर्माता द्वारा आपूर्ति की गई एमुलेशन लिबास के अनुरूप एक प्रारूप शामिल होता है)। इसलिए सभी कंपाइलर एक का उपयोग नहीं कर सकते हैं। बस यह निर्भर करता है कि जब आप "मानक और / या पोर्टेबल" पूछते हैं, तो सिद्धांत में पोर्टेबल और व्यवहार में पोर्टेबल है।
स्टीव जेसप

3
IEEE 754 के लिए आप जो कहते हैं वह सच है, लेकिन मानक को इस एन्कोडिंग के उपयोग की आवश्यकता नहीं है (जैसा कि @SteveJessop बताते हैं, व्यवहार में पोर्टेबल सिद्धांत रूप में पोर्टेबल नहीं है)।
क्रिस्टोफ़

44

सी में, का उपयोग करें

#include <float.h>

const double lowest_double = -DBL_MAX;

C ++ पूर्व -11 में, उपयोग करें

#include <limits>

const double lowest_double = -std::numeric_limits<double>::max();

C ++ 11 और बाद में, का उपयोग करें

#include <limits>

constexpr double lowest_double = std::numeric_limits<double>::lowest();

min()C ++ 11 से पहले फ़ंक्शन उपलब्ध नहीं था ? या कि एक अलग मूल्य से है -max()? en.cppreference.com/w/cpp/types/numeric_limits
एलेक्सिस विल्के

5
@ एलेक्सिस: यदि आप अपने द्वारा लिंक किए गए पृष्ठ पर तालिका में सबसे कम तीन पंक्तियों को देखते हैं, तो आप देखेंगे कि minआपको परिमाण में सबसे छोटा सकारात्मक मान और परिमाण lowestमें सबसे बड़ा ऋणात्मक मान प्राप्त होता है। हाँ, यह भयानक है। C ++ मानक पुस्तकालय की शानदार दुनिया में आपका स्वागत है :-P
रुबनेव

C के लिए इसे परिभाषित किया गया है float.hlimits.hपूर्णांक के लिए है
Ciprian Tomoiagă

33

इसे इस्तेमाल करे:

-1 * numeric_limits<double>::max()

संदर्भ: numeric_limits

यह वर्ग प्रत्येक मौलिक प्रकारों के लिए विशिष्ट है, जिसके सदस्य वापस लौटते हैं या उन विभिन्न मूल्यों पर सेट होते हैं जो उस प्रकार के गुणों को परिभाषित करते हैं जो उस विशिष्ट प्लेटफ़ॉर्म में हैं जिसमें वह संकलित करता है।


1
सिर्फ क्यों नहीं -numeric_limits<double>::max()?
k06a

4
@ k06a को एक एकल वर्ण द्वारा इतनी लंबी अभिव्यक्ति में दर्शाया गया नकारात्मक होना, जहां स्ट्रिंग भी "अधिकतम" कहती है, किसी को जल्द या बाद में मिलना सुनिश्चित है। या तो यह एक वर्णनात्मक चर में संग्रहीत है, या -1 * ...इसे थोड़ा स्पष्ट करने के लिए उपयोग करें।
फ़िलिप हाग्लंड

20

क्या आप वास्तविक अनंत या न्यूनतम परिमित मूल्य की तलाश कर रहे हैं? यदि पूर्व, का उपयोग करें

-numeric_limits<double>::infinity()

जो केवल अगर काम करता है

numeric_limits<double>::has_infinity

अन्यथा, आपको उपयोग करना चाहिए

numeric_limits<double>::lowest()

जो C ++ 11 में पेश किया गया था।

यदि lowest()उपलब्ध नहीं है, तो आप वापस आ सकते हैं

-numeric_limits<double>::max()

जो lowest()सिद्धांत से भिन्न हो सकता है , लेकिन सामान्य रूप से व्यवहार में नहीं आता है।


परिमित और अनंत मूल्य के बीच अंतर के लिए +1! लेकिन मानक एक सममित फ्लोटिंग पॉइंट एन्कोडिंग की गारंटी नहीं देता है। तो -numeric_limits<double>::max()भले ही यह व्यवहार में काम करता है सिद्धांत में पूरी तरह से पोर्टेबल नहीं है।
क्रिस्टोफ़


10

एक सही मायने में पोर्टेबल सी ++ समाधान

C ++ 11 से आप उपयोग कर सकते हैं numeric_limits<double>::lowest()। मानक के अनुसार, यह वही देता है जो आप खोज रहे हैं:

एक परिमित मूल्य x ऐसा है कि जहाँ कोई अन्य परिमित मूल्य y नहीं है y < x
जिसमें सभी विशेषज्ञता के लिए सार्थक is_bounded != false

ऑनलाइन डेमो


गैर पोर्टेबल C ++ के बहुत सारे जवाब यहाँ!

इसके लिए कई जवाब दिए जा रहे हैं -std::numeric_limits<double>::max()

सौभाग्य से, वे ज्यादातर मामलों में अच्छा काम करेंगे। फ़्लोटिंग पॉइंट एन्कोडिंग योजनाएं एक मंटिसा और एक घातांक में एक संख्या को विघटित करती हैं और उनमें से अधिकांश (जैसे लोकप्रिय IEEE-754 ) एक अलग साइन बिट का उपयोग करती हैं, जो मंटिसा से संबंधित नहीं है। यह केवल साइन को फ़्लिप करके सबसे छोटे ऋणात्मक में सबसे बड़े सकारात्मक को बदलने की अनुमति देता है:

यहाँ छवि विवरण दर्ज करें

ये पोर्टेबल क्यों नहीं हैं?

मानक किसी भी फ्लोटिंग पॉइंट मानक को लागू नहीं करता है।

मैं सहमत हूं कि मेरा तर्क थोड़ा सा सिद्धांतवादी है, लेकिन मान लीजिए कि कुछ एक्सटेंट्रिक कंपाइलर निर्माता एक क्रांतिकारी एन्कोडिंग योजना का उपयोग करेंगे जिसमें एक दो के पूरक के कुछ रूपों में एन्कोड किया गया मंटिसा है । दो के पूरक एन्कोडिंग सममित नहीं हैं। उदाहरण के लिए एक हस्ताक्षरित 8 बिट चार के लिए अधिकतम सकारात्मक 127 है, लेकिन न्यूनतम नकारात्मक -128 है। तो हम कल्पना कर सकते हैं कि कुछ फ्लोटिंग पॉइंट एन्कोडिंग समान असममित व्यवहार दिखाते हैं।

मुझे उस तरह की किसी भी एन्कोडिंग योजना के बारे में पता नहीं है, लेकिन मुद्दा यह है कि मानक यह गारंटी नहीं देता है कि साइन फ़्लिप करने से इच्छित परिणाम प्राप्त होता है । तो इस लोकप्रिय उत्तर (क्षमा करें दोस्तों!) को पूरी तरह से पोर्टेबल मानक समाधान के रूप में नहीं माना जा सकता है! / * कम से कम ऐसा नहीं है यदि आपने दावा नहीं किया है कि numeric_limits<double>::is_iec559यह सच है / /



1

मूल प्रश्न अनंत की चिंता करता है। तो, क्यों नहीं उपयोग करें

#define Infinity  ((double)(42 / 0.0))

IEEE परिभाषा के अनुसार? आप निश्चित रूप से इसे नकार सकते हैं।


अछा सुझाव ! और यह काम करता है । लेकिन केवल अगरnumeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
क्रिस्टोफ

1

क्या C (++) प्रोग्राम में सबसे छोटे ऋणात्मक मान (जैसे नकारात्मक अनंत का उपयोग करने के लिए) का प्रतिनिधित्व करने के लिए एक मानक और / या पोर्टेबल तरीका है?

C दृष्टिकोण।

कई कार्यान्वयन +/- शिशुओं का समर्थन करते हैं, इसलिए सबसे नकारात्मक doubleमूल्य है -INFINITY

#include <math.h>
double most_negative = -INFINITY;

क्या कोई मानक और / या पोर्टेबल तरीका है ....?

अब हमें अन्य मामलों पर भी विचार करने की आवश्यकता है:

  • कोई असीमता नहीं

बस -DBL_MAX

  • केवल एक अहस्ताक्षरित अनंत।

मुझे उम्मीद है कि इस मामले में, ओपी पसंद करेगा -DBL_MAX

  • से अधिक परिमाण में सामान्य-सामान्य मान DBL_MAX

यह एक असामान्य मामला है, ओपी की चिंता के बाहर होने की संभावना है। जब वांछित सीमा / पूर्वता प्राप्त करने के लिए फ्लोटिंग पॉइंटdouble की एक जोड़ी के रूप में एन्कोड किया जाता है , ( डबल-डबल देखें ) वहाँ एक अधिकतम सामान्य और शायद एक अधिक डी-सामान्य मौजूद है। मैंने बहस देखी है कि दोनों में से सबसे बड़ी सामान्य को देखें । doubleDBL_MAX

सौभाग्य से इस युग्मित दृष्टिकोण में आमतौर पर एक इनफिनिटी शामिल होती है, इसलिए सबसे नकारात्मक मूल्य बना रहता है -INFINITY


अधिक पोर्टेबिलिटी के लिए, कोड मार्ग से नीचे जा सकता है

// HUGE_VAL is designed to be infinity or DBL_MAX (when infinites are not implemented)
// .. yet is problematic with unsigned infinity.
double most_negative1 = -HUGE_VAL;  

// Fairly portable, unless system does not understand "INF"
double most_negative2 = strtod("-INF", (char **) NULL);

// Pragmatic
double most_negative3 = strtod("-1.0e999999999", (char **) NULL);

// Somewhat time-consuming
double most_negative4 = pow(-DBL_MAX, 0xFFFF /* odd value */);

// My suggestion
double most_negative5 = (-DBL_MAX)*DBL_MAX;

-1

यदि आपके पास फ्लोट अपवाद सक्षम नहीं है (जिसे आपको imho नहीं करना चाहिए), तो आप बस कह सकते हैं:

double neg_inf = -1/0.0;

इससे नकारात्मक अनंतता पैदा होती है। यदि आपको फ्लोट की आवश्यकता है, तो आप या तो परिणाम डाल सकते हैं

float neg_inf = (float)-1/0.0;

या एकल परिशुद्धता अंकगणित का उपयोग करें

float neg_inf = -1.0f/0.0f;

परिणाम हमेशा समान होता है, दोनों एकल और दोहरे परिशुद्धता में नकारात्मक अनंतता का एक ही प्रतिनिधित्व होता है, और वे एक-दूसरे में परिवर्तित होते हैं जैसा कि आप उम्मीद करेंगे।


आप ऐसा सिर्फ लिखने के बजाय क्यों करेंगे-INFINITY
MM

इसके अलावा, अनन्तता मौजूद हो सकती है या नहीं भी हो सकती है और यदि यह मौजूद है तो सकारात्मक और नकारात्मक भिन्न नहीं हो सकते हैं (मानक C में)।
एमएम

कई कंपाइलर और / या आर्किटेक्चर में आपका C / C ++ कोड आपको अनंत और NaN मानों को फैलाने में बहुत धीमा कर देगा।
मार्कगलासी

@markgalassi कृपया ध्यान दें: आप देखेंगे कि neg_infएक स्थिर मूल्य के लिए इनिशियलाइज़ किया गया है । संकलक infमूल्य की गणना का ध्यान रखेगा । और जब आप इसे अधिकतम कंप्यूटिंग के लिए अशक्त मान के रूप में उपयोग करते हैं, तो पहला पुनरावृत्ति आम तौर पर इसे एक बड़े मूल्य के साथ अधिलेखित कर देगा। यानी प्रदर्शन शायद ही एक समस्या है। और ओपी विशेष रूप से "उदासीनता का उपयोग करने के लिए उदासीनता" के बारे में पूछता है, और -infवास्तव में इसका एकमात्र सही उत्तर है। आपने एक सही और उपयोगी उत्तर दिया है।
सेंटास्टर -
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.