2011-04-02 10 views
7

मैं कैसे मुद्रित कर सकते हैं (कि stdout के लिए, है) सी में एक नाव बिना होने यह एक डबल पर पदोन्नत होने जब printf के लिए पारित variadic पैरामीटर पदोन्नति से परहेज?सी में एक नाव प्रिंट करते समय दोगुना करने के लिए

यहां मुद्दा यह है कि सी में variadic कार्यों डबल है, जो दो अनावश्यक रूपांतरण पड़ता है करने के लिए सभी नाव पैरामीटर को बढ़ावा देने है। उदाहरण के लिए, यदि आप जीसीसी में -Wdouble पदोन्नति पर बारी और संकलन

float f = 0.f; 
printf("%f", f); 

आप

warning: implicit conversion from 'float' to 'double' when passing argument to function 

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

क्या सीधे सी में फ्लोट को अधिक कुशलतापूर्वक प्रिंट करने का कोई तरीका है?

+1

किसी को भी इस भर आता है, तो मैं समाप्त हो गया बस अपना डेटा base64'ing, और डीकोड/स्वरूपित/सुंदर मुद्रित एक मेजबान machine.I पर सब कुछ भी बूस्ट :: कर्म माना जाता है, लेकिन उसमें सी ++ की आवश्यकता होती और वहां एक अच्छा मौका था कि यह मुझे कोई कोड आकार नहीं बचाएगा। –

उत्तर

7

पदोन्नति से बचना है, तो आप कुछ भी बचा नहीं पाएगा आंतरिक double के बाद से (या अधिक होने की संभावना long double) अंकगणित printf प्रदर्शन करेंगे ज्यादा समय के रूप में कम से कम 1000x उपभोग करने के लिए जा रहा है। सटीक रूप से फ़्लोटिंग पॉइंट मान प्रिंटिंग आसान नहीं है

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

या फिर आप की तरह कुछ कर सकता है:

printf("%d.%.6d", (int)x, (int)((x-(int)x)*1000000)); 
+0

मुझे एहसास हुआ कि प्रिंट करने के लिए मुझे आवश्यक अधिकांश फ्लोट [0, 1] की सीमा में थीं, इसलिए मैं प्रिंटिंग के लिए पूर्णांक के लिए उनको घूमने में सक्षम था। काफी सुधार से यह बेहतर प्रदर्शन। –

5

दुर्भाग्यवश, printf में सादे फ्लोट को सौंपने के लिए समर्थन नहीं है: एस।

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

यदि दूसरी तरफ, आप बस चेतावनी से छुटकारा पाने के लिए चाहते हैं, तो आप float को double पर स्पष्ट रूप से डाले जा सकते हैं।

2

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

+0

मैं सहमत नहीं हूं। एस्पसी रूपांतरणों के लिए फ़्लोटिंग-पॉइंट का सबसे महंगा हिस्सा 10 से विभाजन है। और फ्लोट पर काम करते हुए और डबल पर नहीं होने पर वे तेज़ी से बढ़ते हैं। –

+0

@edgar: निश्चित रूप से फ़्लोटिंग पॉइंट ऑप्स शामिल हैं जो फ्लोट्स की तुलना में दोगुनी से अधिक लागत लेते हैं। लेकिन 10 कार्यान्वयन से div lib के कार्यान्वयन पर निर्भर करता है। आप अंक प्राप्त करने के लिए पूर्णांक संचालन के साथ मंटिसा बिट्स पर भी काम कर सकते हैं। यह प्रयुक्त libc पर भारी निर्भर करता है (जो आमतौर पर एम्बेडेड के लिए एक पूर्ण बड़ा कार्यान्वयन नहीं है)। Thats क्यों मैंने कहा कि आपको एक निश्चित जवाब के लिए प्रोफ़ाइल की जरूरत है। और बचने का एकमात्र तरीका अपना स्वयं का कार्य लिख रहा है। – flolo

0
  • पहला दृष्टिकोण: printf के बजाय ftoa का उपयोग करें। प्रोफ़ाइल।

  • बढ़ी हुई आउटपुट लचीलापन के लिए, मैं आपके कंपाइलर की एसडीडीआईबी के स्रोत कोड में जाऊंगा, शायद जीसीसी के कुछ व्युत्पन्न, प्रिंटफ कार्यान्वयन का पता लगाएं और डबल कोड> एएससीआई रूपांतरण के लिए प्रासंगिक कोड पर प्रतिलिपि बनाएँ। इसे तैरने के लिए लिखें -> ascii।

  • अगला, मैन्युअल रूप से एक या दो प्रमुख कॉल-साइट को अपने नए (गैर-वैरिएडिक) संस्करण में बदलें और इसे प्रोफाइल करें।

  • यदि यह आपकी समस्या का समाधान करता है, तो आप stdlib से संस्करण के आधार पर अपने स्वयं के printf को फिर से लिखने के बारे में सोच सकते हैं, जिससे फ्लोट के बजाय आप फ्लोट * पास करते हैं। इसे स्वचालित पदोन्नति से छुटकारा पाना चाहिए।

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