2012-02-10 20 views
15

मैं std::cout पोर्टेबल (जीसीसी, क्लैंग, एमएसवीसी ++) के लिए एक डबल वैल्यू प्रिंट करना चाहता हूं ताकि आउटपुट सभी प्लेटफार्मों पर समान हो।डबल टू सी ++ iostreams के एक्सपोनेंट की पोर्टेबल प्रिंटिंग

मुझे एक्सपोनेंट के स्वरूपण में कोई समस्या है। मैं दोनों एक ही आउटपुट कैसे कर सकते हैं

1e-08 

और MSVC

1e-008 

साथ निम्नलिखित उत्पादन: निम्नलिखित कार्यक्रम

#include <iostream> 
int main() 
{ 
    std::cout << 0.1e-7 << std::endl; 
    return 0; 
} 

जीसीसी के साथ इस उत्पादन गया है?

मुझे खेद है कि यह एक बेवकूफ सवाल है लेकिन मुझे अब तक कोई जवाब नहीं मिला है। सभी स्वरूपण अपूर्णांश से पहले सब कुछ के स्वरूपण के आसपास विकसित करने के लिए ...

संपादित लगता है: जीसीसी के उत्पादन 1e-08 नहीं 1e-8 (के रूप में मूल रूप से कहा गया है) तो यह है अनुरूप है। गलतफहमी के लिए खेद है।

EDIT2: डायटमार की टिप्पणी के बाद वास्तव में "मंथिसा" को "एक्सपोनेंट" नाम दिया गया। There also is a section on Wikipedia on mantissa vs. significant

+0

आप [manipulators] को देखा है मुद्रित करने के लिए कैसे (http://www.cplusplus.com/reference/iostream/manipulators/)? – razlebe

+1

@razlebe: मुझे मैनिपुलेटर्स का उपयोग करने में कोई जवाब नहीं मिला। – Manuel

+0

मुझे जीसीसी असंगत लगता है क्योंकि यह '1.e-08' और' 1.e-18' (दो अंक) प्रिंट करता है और फिर भी यह '1.e-256' (तीन अंक) प्रिंट करता है। मुझे एक स्ट्रीम लाइब्रेरी नहीं मिल सका जो इसे हल करता है (मैंने कोर्स के आईस्ट्रीम और बूस्ट.फॉर्मैट के साथ प्रयास किया)। इसलिए यदि कोई निश्चित चौड़ाई दोगुना करना चाहता है तो उसे एक्सपोनेंट के संभावित तीसरे अंक के लिए आरक्षित और अतिरिक्त जगह की आवश्यकता होती है। – alfC

उत्तर

11

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

एकमात्र दृष्टिकोण जिसे मैं जानता हूं वह अपने std::num_put<char> पहलू का उपयोग करना है जो वांछित मानों को स्वरूपित करता है। इस पहलू को std::locale में रखा जाएगा जो बदले में imbue() एड std::cout में है। फ्लोटिंग पॉइंट नंबर को प्रारूपित करने के लिए एक संभावित कार्यान्वयन डिफ़ॉल्ट std::num_put<char> पहलू (या snprintf(), दुर्भाग्य से, शायद सरल) का उपयोग कर सकता है और फिर एक्सपोनेंट से अग्रणी शून्य को स्ट्रिप कर सकता है। MSVC _set_output_format समारोह जो आप "दो अंकों के रूप में प्रिंट प्रतिपादक" करने के लिए स्विच करने के लिए उपयोग कर सकते हैं प्रदान करता है:

+4

सी ++ स्वरूपण को 'printf' के संदर्भ में परिभाषित किया गया है, जो कहता है कि "एक्सपोनेंट में कम से कम दो अंक होंगे।" (इसलिए जी ++ अनुरूप नहीं है।) मैं यहां पॉज़िक्स मानक से पढ़ रहा हूं, जिसे सी मानक के अनुरूप माना जाता है। लेकिन मेरे पास पाठ की अस्पष्ट यादें हैं कि यह आवश्यक होने तक दो से अधिक वर्ण नहीं हो सकता है (जो वीसी को भी गलत बना देगा); मुझे याद है कि लंबे समय से इस पर चर्चा की गई थी, और यह स्थापित किया गया था कि वीसी गैर-अनुरूप था (यदि समस्या का समाधान नहीं होता है तो वह समस्या का समाधान नहीं करता है)। –

+1

@JamesKanze इसे पढ़ना संभव है जैसे कि उनका मतलब अंकों के बजाय "चरित्र" था, जिस स्थिति में ऋण चिह्न गिना जाएगा? – Flexo

+0

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

3

जबकि डिटमार का जवाब साफ है और शायद ही वास्तव में पोर्टेबल जवाब है, मैं गलती से एक त्वरित और गंदा जवाब मिल गया।

निम्नलिखित आरएआईआई कक्षा को आपके main() फ़ंक्शन में तत्काल किया जा सकता है ताकि आपको जीसीसी, सीएलएएनजी और एमएसवीसी का वही व्यवहार दिया जा सके।

class ScientificNotationExponentOutputNormalizer 
{ 
public: 
    unsigned _oldExponentFormat; 

    ScientificNotationExponentOutputNormalizer() : _oldExponentFormat(0) 
    { 
#ifdef _MSC_VER 
     // Set scientific format to print two places. 
     unsigned _oldExponentFormat = _set_output_format(_TWO_DIGIT_EXPONENT); 
#endif 
    } 

    ~ScientificNotationExponentOutputNormalizer() 
    { 
#ifdef _MSC_VER 
     // Enable old exponent format. 
     _set_output_format(_oldExponentFormat); 
#endif 
    } 
}; 
+0

यह कम से कम MSVCR80.dll की आवश्यकता है जो MinGW के साथ काम करने के लिए सेटअप करने के लिए दर्दनाक है। – Manuel

+0

नोट: जैसा कि दस्तावेज़ में बताया गया है, 'यह फ़ंक्शन अप्रचलित है। विजुअल स्टूडियो 2015 में शुरुआत, यह सीआरटी में उपलब्ध नहीं है – BenC

2

समस्या यह है कि दृश्य सी ++ सी 99 मानक का पालन नहीं कर रहा था।

%e और %E प्रारूप विनिर्देशक एक दशमलव अपूर्णांश और प्रतिपादक के रूप में एक चल बिन्दु संख्या स्वरूप: 2015 ++ विज़ुअल सी में, _set_output_format के बाद से संकलक अब मानक इस प्रकार है हटा दिया गया था। %g और %G प्रारूप विनिर्देशक कुछ मामलों में इस फ़ॉर्म में संख्याओं को प्रारूपित करते हैं। पिछले संस्करणों में, सीआरटी हमेशा तीन अंकों के एक्सपोनेंट के साथ स्ट्रिंग उत्पन्न करेगा।उदाहरण के लिए, printf("%e\n", 1.0)1.000000e+000 प्रिंट करेगा। यह गलत था: सी की आवश्यकता है कि यदि एक्सपोनेंट केवल एक या दो अंकों का उपयोग करके प्रतिनिधित्व योग्य है, तो केवल दो अंक मुद्रित किए जाएंगे

विजुअल स्टूडियो 2005 में एक वैश्विक अनुरूपता स्विच जोड़ा गया: _set_output_format। एक प्रोग्राम अभिव्यक्ति एक्सपोनेंट प्रिंटिंग को सक्षम करने के लिए, _TWO_DIGIT_EXPONENT तर्क के साथ इस फ़ंक्शन को कॉल कर सकता है। डिफ़ॉल्ट व्यवहार को मानक-बदलते एक्सपोनेंट प्रिंटिंग मोड में बदल दिया गया है।

Breaking Changes in Visual C++ 2015 देखें। पुराने संस्करणों के लिए, @ मैनुअल का जवाब देखें।

FYI करें, C99 standard में, हम पढ़ सकते हैं:

ई, ई

एक डबल तर्क एक फ्लोटिंग प्वाइंट संख्या का प्रतिनिधित्व शैली में बदल जाती है [-] d.ddd ई (+ -) डीडी, जहां दशमलव बिंदु बिंदु से पहले एक अंक (जो गैर-शून्य है तो तर्क nonzero है) और अंकों के बाद सटीक के बराबर है; यदि परिशुद्धता गुम है, तो इसे 6 के रूप में लिया जाता है; यदि परिशुद्धता शून्य है और # ध्वज निर्दिष्ट नहीं है, तो कोई दशमलव-बिंदु वर्ण प्रकट नहीं होता है। मूल्य अंकों की उचित संख्या के लिए गोल किया जाता है। ई रूपांतरण विनिर्देशक एक्स के बजाय ई के साथ एक संख्या उत्पन्न करता है। एक्सपोनेंट में कम से कम दो अंक होते हैं, और एक्सपोनेंट का प्रतिनिधित्व करने के लिए आवश्यक जितना अधिक अंक होते हैं। यदि मान शून्य है, तो एक्सपोनेंट शून्य है। एक अनंत या NaN का प्रतिनिधित्व करने वाला एक डबल तर्क एक एफ या एफ रूपांतरण विनिर्देशक की शैली में परिवर्तित हो जाता है।

यह सी 9 0 की तुलना में एक अंतर है जिसने आवश्यक एक्सपोनेंट लंबाई से संबंधित कोई संकेत नहीं दिया है।

नोट हाल विजुअल C++ परिवर्तन भी चिंता का विषय है कि nan, inf आदि

संबंधित मुद्दे