मैं पूरी सटीकता के साथ cout का उपयोग करके एक डबल मान कैसे प्रिंट करूं?


331

इसलिए मैंने अपने अंतिम प्रश्न का उत्तर पा लिया है (मुझे नहीं पता कि मैंने ऐसा क्यों नहीं सोचा)। जब मैं इसकी उम्मीद नहीं कर रहा था तो मैं एक राउंड doubleका उपयोग कर coutरहा था। मैं पूर्ण सटीकता का उपयोग करके coutप्रिंट कैसे बना सकता हूं double?

जवाबों:


390

आप सटीक को सीधे सेट कर सकते std::coutहैं और std::fixedप्रारूप विनिर्देशक का उपयोग कर सकते हैं ।

double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;

आप #include <limits>एक फ्लोट या डबल की अधिकतम परिशुद्धता प्राप्त कर सकते हैं ।

#include <limits>

typedef std::numeric_limits< double > dbl;

double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;

46
आप स्पष्ट रूप से उपयोग करने की सलाह क्यों देते हैं fixed? के साथ double h = 6.62606957e-34;, fixedमुझे 0.000000000000000और scientificआउटपुट देता है 6.626069570000000e-34
आर्थर

36
सटीक को 17 (या std :: num_limits <double> :: digits10 + 2) की आवश्यकता होती है क्योंकि 2 अतिरिक्त अंकों की आवश्यकता होती है जब यह सुनिश्चित करने के लिए दशमलव वापस से बाइनरी प्रतिनिधित्व में परिवर्तित किया जाता है कि मूल्य एक ही मूल मान के लिए गोल है। यहाँ कुछ विवरणों के साथ एक पेपर दिया गया है: docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
माइक फिशर

8
क्या वास्तव में सही उत्तर है? जब मैं मैन्युअल रूप से एक उच्च संख्या का उपयोग करता हूं, तो मैं अनुमानित ई के 51 अंकों के रूप में प्रिंट कर सकता हूं, लेकिन cout.precision(numeric_limits<double>::digits10 + 2);मैं केवल 16 प्राप्त कर सकता हूं ...
एसिमिलाटर

6
पेपर में 17 अंकों का उल्लेख करने वालों के लिए @MikeFisher ने उद्धृत किया, यह Theorem 15. के अंतर्गत है
Emile Cormier

15
@ मायकेफिशर आप सही कह रहे हैं, सी ++ 11max_digits10 उसी को निरूपित करने के लिए परिचय देता है। इसे दर्शाने के लिए उत्तर निश्चित किया।
लीजेंड्स 2

70

उपयोग करें std::setprecision:

std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;

2
क्या किसी प्रकार का MAX_PRECISION मैक्रो या एनुम या कुछ है जो मैं एसटीडी पास कर सकता हूं: सेटप्रीकेशन?
जेसन Punyon

2
std :: setpreaches (15) एक डबल (ठीक या 16) के लिए, log_10 (2 ** 53) ~ = 15.9
user7116

14
std :: setprepy (std :: num_limits <double> :: digits10)
Malric Malenfant

6
std::setprecision (17)डबल के लिए होना चाहिए , @Bill The Lizard के जवाब पर टिप्पणियां देखें।
एलेक जैकबसन

9
एसटीडी के लिए :: काम करने के लिए सेपरेटेज, #include <iomanip> को शामिल किया जाना चाहिए।
user2262504

24

यहाँ मैं क्या उपयोग होगा:

std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
          << 3.14159265358979
          << std::endl;

मूल रूप से सीमा पैकेज में सभी प्रकार के निर्माण के लिए लक्षण हैं।
फ्लोटिंग पॉइंट नंबर (फ्लोट / डबल / लॉन्ग डबल) के लिए लक्षणों में से एक अंक 10 विशेषता है। यह आधार 10 में एक फ्लोटिंग पॉइंट नंबर की सटीकता (मैं सही शब्दावली भूल जाता है) को परिभाषित करता है।

देखें: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
अन्य विशेषताओं के बारे में जानकारी के लिए।


12
इस शीर्ष लेख का उपयोग करने की आवश्यकता है std::setprecision(): #include <iomanip>
मार्टिन बर्जर

इसके std::numeric_limits<double>बजायnumberic_limits<double>
niklasfi

2
आप क्यों जोड़ते 1हैं std::numeric_limits<double>::digits10?
बजे एलेसेंड्रो जैकप्सन

5
@ लोकीअस्तरी आप C + 11 के max_digits10बजाय उपयोग कर सकते हैं । देखें इस
लीजेंड्स 2k

1
@AlecJacobson यह होना चाहिए max_digits10, न कि कुछ मनमाना digits10+2। अन्यथा, के मामले में float, long double, boost::multiprecision::float128इस, असफल वहाँ जब से तुम आवश्यकता होगी होगा +3के बजाय +2
रुस्लान

14

Iostreams रास्ता क्लंकी की तरह है। मैं उपयोग करना पसंद करता हूं boost::lexical_castक्योंकि यह मेरे लिए सही परिशुद्धता की गणना करता है। और यह तेज भी है।

#include <string>
#include <boost/lexical_cast.hpp>

using boost::lexical_cast;
using std::string;

double d = 3.14159265358979;
cout << "Pi: " << lexical_cast<string>(d) << endl;

आउटपुट:

पाई: 3.14159265358979


बूस्ट डॉक्यूमेंटेशन में कहा गया है, "संख्यात्मक के लिए जिनके पास std का एक समान विशेषज्ञता है: num_limits, वर्तमान संस्करण अब मैच के लिए एक सटीक चुनता है"। यह अधिकतम परिशुद्धता प्राप्त करने का सबसे आसान तरीका लगता है। ( boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/… )
JDiMatteo

11

पूर्ण परिशुद्धता के द्वारा, मेरा मतलब है कि पर्याप्त सटीकता सटीक मान के लिए सबसे अच्छा सन्निकटन दिखाने के लिए है, लेकिन यह इंगित किया जाना चाहिए कि doubleबेस 2 प्रतिनिधित्व का उपयोग करके संग्रहीत किया गया है और बेस 2 1.1बिल्कुल भी तुच्छ के रूप में कुछ का प्रतिनिधित्व नहीं कर सकता है। वास्तविक डबल (NO ROUND OFF ERROR के साथ) की पूर्ण-पूर्ण परिशुद्धता प्राप्त करने का एकमात्र तरीका द्विआधारी बिट्स (या हेक्स नाइबल्स) को प्रिंट करना है। कि करने का एक तरीका लिख रहा है doubleएक करने के लिए unionऔर फिर बिट्स के पूर्णांक मान बाहर मुद्रण।

union {
    double d;
    uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;

यह आपको दोहरी की 100% सटीक सटीकता देगा ... और पूरी तरह से अपठनीय हो क्योंकि मनुष्य IEEE डबल प्रारूप नहीं पढ़ सकता है! विकिपीडिया पर द्विआधारी बिट्स की व्याख्या करने के बारे में एक अच्छा लिखना है।

नए C ++ में, आप कर सकते हैं

std::cout << std::hexfloat << 1.1;

10

यहां बताया गया है कि पूरी सटीकता के साथ डबल कैसे प्रदर्शित करें:

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;

यह प्रदर्शित करता है:

100.0000000000005


max_digits10 अंकों की संख्या है जो विशिष्ट रूप से सभी विशिष्ट दोहरे मूल्यों का प्रतिनिधित्व करने के लिए आवश्यक हैं। दशमलव बिंदु से पहले और बाद में max_digits10 अंकों की संख्या का प्रतिनिधित्व करता है।


Std :: फिक्स्ड के साथ set_prepy (max_digits10) का उपयोग न करें।
निश्चित संकेतन पर, set_preaches () दशमलव बिंदु के बाद ही अंकों की संख्या निर्धारित करता है । यह गलत है क्योंकि max_digits10 दशमलव बिंदु से पहले और बाद में अंकों की संख्या का प्रतिनिधित्व करता है ।

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;

यह गलत परिणाम प्रदर्शित करता है:

100.00000000000049738

नोट: हेडर फ़ाइलों की आवश्यकता है

#include <iomanip>
#include <limits>

4
ऐसा इसलिए होता है क्योंकि 100.0000000000005इसका प्रतिनिधित्व बिल्कुल नहीं किया जाता है double। (ऐसा लग सकता है कि यह होना चाहिए, लेकिन ऐसा नहीं है, क्योंकि यह सामान्य हो जाता है , अर्थात इसका द्विआधारी प्रतिनिधित्व)। इसे देखने के लिए, प्रयास करें 100.0000000000005 - 100:। हमें मिलता है 4.973799150320701e-13
एवगेनी

9

मैं doubleपूर्ण सटीकता के साथ cout का उपयोग करके एक मूल्य कैसे प्रिंट करूं ?

सटीक का उपयोग करें hexfloatया
उपयोग करें scientificऔर सेट करें

std::cout.precision(std::numeric_limits<double>::max_digits10 - 1);
std::cout << std::scientific <<  1.0/7.0 << '\n';

// C++11 Typical output
1.4285714285714285e-01

बहुत सारे उत्तर केवल 1 में से एक) आधार 2) को निर्धारित / वैज्ञानिक लेआउट या 3) परिशुद्धता से संबोधित करते हैं। परिशुद्धता के साथ बहुत से उत्तर आवश्यक उचित मूल्य प्रदान नहीं करते हैं। इसलिए यह एक पुराने प्रश्न का उत्तर है।

  1. क्या आधार है?

A doubleनिश्चित रूप से आधार का उपयोग कर एन्कोड किया गया है। C ++ 11 के साथ एक सीधा दृष्टिकोण का उपयोग करके प्रिंट करना है std::hexfloat
यदि एक गैर-दशमलव आउटपुट स्वीकार्य है, तो हम किए जाते हैं।

std::cout << "hexfloat: " << std::hexfloat << exp (-100) << '\n';
std::cout << "hexfloat: " << std::hexfloat << exp (+100) << '\n';
// output
hexfloat: 0x1.a8c1f14e2af5dp-145
hexfloat: 0x1.3494a9b171bf5p+144

  1. अन्यथा: fixedया scientific?

A doubleएक फ्लोटिंग पॉइंट प्रकार है, फिक्स्ड पॉइंट नहीं है

करो नहीं का उपयोग std::fixedकि के रूप में छोटे मुद्रित करने के लिए विफल रहता है doubleकुछ भी लेकिन के रूप में 0.000...000। बड़े के लिए double, यह कई अंकों को प्रिंट करता है, शायद सैकड़ों संदिग्ध सूचनात्मकता।

std::cout << "std::fixed: " << std::fixed << exp (-100) << '\n';
std::cout << "std::fixed: " << std::fixed << exp (+100) << '\n';
// output
std::fixed: 0.000000
std::fixed: 26881171418161356094253400435962903554686976.000000 

पूर्ण परिशुद्धता के साथ प्रिंट करने के लिए, पहले std::scientific"वैज्ञानिक अंकन में फ्लोटिंग-पॉइंट मान" लिखेंगे। दशमलव बिंदु, एक अपर्याप्त राशि के बाद 6 अंकों के डिफ़ॉल्ट को नोटिस करें, अगले बिंदु में संभाला जाता है।

std::cout << "std::scientific: " << std::scientific << exp (-100) << '\n';  
std::cout << "std::scientific: " << std::scientific << exp (+100) << '\n';
// output
std::scientific: 3.720076e-44
std::scientific: 2.688117e+43

  1. कितनी सटीकता (कितने कुल अंक)?

doubleबाइनरी बेस 2 का उपयोग करके एक एन्कोडेड 2 की विभिन्न शक्तियों के बीच एक ही परिशुद्धता को एन्कोड करता है। यह अक्सर 53 बिट्स होता है।

[१.० ... २.०) २ ५३ भिन्न हैं double,
[२.० ... ४.०) २ ५३ भिन्न हैं double,
[४.० ... there.०) २ ५३ भिन्न हैं double,
[10.0. 10.0 ... १०)] २ / हैं * २ ५३ अलग double

फिर भी यदि कोड Nमहत्वपूर्ण अंकों के साथ दशमलव में प्रिंट करता है , तो संयोजनों की संख्या [1.0 ... 10.0) 9/10 * 10 N है

जो भी N(सटीक) चुना जाता है, उसके बीच doubleऔर दशमलव पाठ में एक-से-एक मैपिंग नहीं होगी । यदि कोई निश्चित Nचुना जाता है, तो कभी-कभी यह कुछ doubleमूल्यों के लिए वास्तव में आवश्यक से थोड़ा अधिक या कम होगा । हम बहुत कम ( a)नीचे) या बहुत अधिक ( b)नीचे) त्रुटि कर सकते हैं ।

3 उम्मीदवार N:

क) Nपाठ से परिवर्तित करते समय एक का उपयोग करें double-इसलिए हम सभी के लिए एक ही पाठ में आते हैं double

std::cout << dbl::digits10 << '\n';
// Typical output
15

b) -text Nसे कनवर्ट करते समय एक का उपयोग doubleकरें- doubleहम doubleसभी के लिए समान हैं double

// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17

जब max_digits10उपलब्ध नहीं है, तो ध्यान दें कि आधार 2 और आधार 10 विशेषताओं के कारण digits10 + 2 <= max_digits10 <= digits10 + 3, हम यह digits10 + 3सुनिश्चित करने के लिए उपयोग कर सकते हैं कि पर्याप्त दशमलव अंक मुद्रित हो।

ग) एक का उपयोग करें जो Nमूल्य के साथ बदलता रहता है।

यह तब उपयोगी हो सकता है जब कोड न्यूनतम पाठ ( N == 1) या ( के मामले में ) का सही मूल्य प्रदर्शित करना चाहता है । फिर भी चूंकि यह "काम" है और ओपी के लक्ष्य की संभावना नहीं है, इसलिए इसे अलग रखा जाएगा।doubleN == 1000-ishdenorm_min


यह आमतौर पर ख) जिसका उपयोग " doubleपूर्ण परिशुद्धता के साथ एक मूल्य प्रिंट करने के लिए" किया जाता है । कुछ एप्लिकेशन बहुत अधिक जानकारी प्रदान करने में त्रुटि के कारण a) को प्राथमिकता दे सकते हैं।

साथ .scientific, .precision()सेट अंकों की संख्या दशमलव बिंदु के बाद मुद्रित करने के लिए है, तो 1 + .precision()अंक मुद्रित कर रहे हैं। कोड को max_digits10कुल अंकों की आवश्यकता होती है इसलिए .precision()इसे a के साथ कहा जाता है max_digits10 - 1

typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10 - 1);
std::cout << std::scientific <<  exp (-100) << '\n';
std::cout << std::scientific <<  exp (+100) << '\n';
// Typical output
3.7200759760208361e-44
2.6881171418161356e+43
//1234567890123456  17 total digits

इसी तरह का सवाल


बहुत बढ़िया जवाब! हालांकि कुछ टिप्पणी: आप सही हैं कि precision()वैज्ञानिक मोड के लिए दशमलव स्थानों की संख्या निर्धारित करता है। निर्दिष्ट किए बिना scientific, यह घातांक को छोड़कर, अंकों की कुल संख्या निर्धारित करता है। आप अपने संख्या मूल्य के आधार पर अभी भी वैज्ञानिक आउटपुट के साथ समाप्त हो सकते हैं, लेकिन फिर आप निर्दिष्ट अंकों से भी कम अंक प्राप्त कर सकते हैं। उदाहरण: भिन्न cout.precision(3); cout << 1.7976931348623158e+308; // "1.8e+308"परिणाम printfहो सकते हैं। भ्रामक सामान किसी को पता होना चाहिए।
सिंपलटन

पोस्टरिटी के लिए, यहां प्रिंटफ का उपयोग करके वैज्ञानिक मोड में सभी दोहरे नंबरों की सटीक स्ट्रिंग प्रतिनिधित्व की गारंटी बफर लंबाई के लिए आवश्यक है: char buf[DBL_DECIMAL_DIG + 3 + 5]; sprintf(buf, "%.*g", DBL_DECIMAL_DIG, d);अतिरिक्त वर्ण निम्न हैं: साइन, दशमलव बिंदु, शून्य से पीछे, ई + + -], घातांक के लिए 3 अंक? DBL_MAX_10_EXP = 308)। इसलिए आवश्यक वर्णों की कुल संख्या 25 है।
सिम्पटन

मेरी पहली टिप्पणी को संपादित नहीं किया जा सकता है, इसलिए यहां हम फिर से जाते हैं: वैज्ञानिक मोड के साथ एक और मुद्दा यह है कि यह घातीय आउटपुट का उपयोग न करने का निर्णय ले सकता है, यहां तक ​​कि यह फ्लोटिंग पॉइंट आउटपुट का उपयोग नहीं करने का निर्णय ले सकता है। यही है, यह 1.0 को "1" के रूप में आउटपुट करेगा, जो कि क्रमबद्धता / डिसरलाइज़ेशन संदर्भ में एक समस्या हो सकती है। आप इसे "% #। * G" का उपयोग करके एक दशमलव बिंदु को आउटपुट करने के लिए बाध्य कर सकते हैं, लेकिन इसका दोष यह है कि यह कई संख्या में अनुगामी शून्य जोड़ता है, जो इसे # के बिना नहीं करता है ...
सिंपलटन

3
printf("%.12f", M_PI);

% .12f का मतलब फ्लोटिंग पॉइंट है, जिसमें 12 अंको की शुद्धता होती है।


11
यह "cout का उपयोग करना" नहीं है।
जॉनसीवेब

2
12 अंक "पूर्ण परिशुद्धता" नहीं है
रोलैंड इलिग

0

अधिकांश रूप से ...

#include <limits>

using std::numeric_limits;

    ...
    cout.precision(numeric_limits<double>::digits10 + 1);
    cout << d;

16
मैं उत्सुक हूं: "+1" क्यों?
9ric Malenfant

0

ओस्ट्रीम के साथ :: परिशुद्धता (इंट)

cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;

निकलेगा

3.141592653589793, 2.718281828459045

आपको "+1" क्यों कहना है, मेरे पास कोई सुराग नहीं है, लेकिन आप जो अतिरिक्त अंक प्राप्त करते हैं, वह सही है।


3
न्यूमेरिक_लिमिट्स <अहस्ताक्षरित चार> :: अंक 10 बराबर होता है। क्योंकि इसमें दो अंकों की कोई भी दशमलव संख्या 0..99 हो सकती है। इसमें 255 भी हो सकते हैं .. लेकिन 256, 257 ... 300 आदि नहीं। यही कारण है कि अंक 10 3 नहीं है! मुझे लगता है कि इस तरह से कुछ को दूर करने के लिए "+1" जोड़ा जाता है।
दिमित्री युचेंको

0

यह डॉट के बाद दो दशमलव स्थानों तक मान दिखाएगा।

#include <iostream>
#include <iomanip>

double d = 2.0;
int n = 2;
cout << fixed << setprecison(n) << d;

यहाँ देखें: फिक्स्ड-पॉइंट नोटेशन

std :: तय

फिक्स्ड फ़्लोटिंग पॉइंट नोटेशन का उपयोग करें। फ़्लो स्ट्रीम फ़ील्ड फ़्लैग को निर्धारित स्ट्रीम के लिए निर्धारित करता है।

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

std :: setprecision

दशमलव सटीक सेट करें आउटपुट ऑपरेशन पर फ़्लोटिंग-पॉइंट मानों को प्रारूपित करने के लिए उपयोग की जाने वाली दशमलव सटीक सेट करता है।

यदि आप फ्लोटिंग-पॉइंट्स का प्रतिनिधित्व करने के लिए IEEE मानक से परिचित हैं, तो आपको पता होगा कि मानक के दायरे से बाहर पूरी-सटीकता के साथ फ्लोटिंग-पॉइंट दिखाना असंभव है , अर्थात यह हमेशा परिणाम देगा वास्तविक मूल्य की एक गोलाई।

आपको पहले यह जांचने की आवश्यकता है कि क्या मान दायरे में है , यदि हाँ, तो उपयोग करें:

cout << defaultfloat << d ;

std :: defaultfloat

डिफ़ॉल्ट फ़्लोटिंग पॉइंट-पॉइंट नोटेशन का उपयोग करें। फ़्लोटफ़ील्ड के लिए फ़्लैटफ़ील्ड के लिए फ़्लैटफ़िल्ड फॉर्मेट फ़्लैग को सेट करता है।

जब फ़्लोटफ़ील्ड को डिफ़ॉल्टफ़्लोट में सेट किया जाता है, फ़्लोटिंग-पॉइंट वैल्यूज़ को डिफॉल्ट नोटेशन का उपयोग करके लिखा जाता है: प्रतिनिधित्व, स्ट्रीम के दशमलव सटीक (सटीक) तक आवश्यक कई सार्थक अंकों का उपयोग करता है, दशमलव बिंदु से पहले और बाद में दोनों अंकों की गणना करता है (यदि कोई हो )।

यह भी डिफ़ॉल्ट व्यवहार है cout, जिसका अर्थ है कि आप इसका स्पष्ट रूप से उपयोग नहीं करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.