2012-06-05 30 views
19

मैं एक प्रोग्राम लिख रहा हूं जो किसी अन्य प्रोग्राम के अंदर फ़्लोटिंग पॉइंट अक्षर का उपयोग करता है।प्रिंटिंग फ्लोट, सटीक संरक्षण

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

चूंकि एक फ्लोट में 24 * (log(2)/log(10)) = 7.2247199 सटीक दशमलव अंक हैं, तो मेरा प्रारंभिक विचार यह था कि प्रिंटिंग 8 अंक पर्याप्त होना चाहिए। लेकिन अगर मैं दुर्भाग्यपूर्ण हूं, तो 0.2247199 बाईं ओर और 7 महत्वपूर्ण अंकों के दाईं ओर वितरित हो जाते हैं, इसलिए मुझे शायद 9 दशमलव अंक प्रिंट करना चाहिए।

क्या मेरा विश्लेषण सही है? क्या 9 दशमलव अंक सभी मामलों के लिए पर्याप्त हैं? printf("%.9g", x); की तरह?

क्या कोई मानक फ़ंक्शन है जो उस मान के लिए आवश्यक दशमलव अंकों की न्यूनतम संख्या के साथ एक स्ट्रैट में एक फ्लोट को परिवर्तित करता है, जहां 7 या 8 पर्याप्त हैं, इसलिए मैं अनावश्यक अंकों को मुद्रित नहीं करता हूं?

नोट: मैं हेक्साडेसिमल फ़्लोटिंग पॉइंट अक्षर का उपयोग नहीं कर सकता, क्योंकि मानक सी ++ उनका समर्थन नहीं करता है।

+1

उपयोग 1000 अंक और अनुगामी शून्य क्लिप! ;) –

+4

क्योंकि आप बिना किसी त्रुटि के बाइनरी-आधारित फ्लोट को दशमलव अंश में परिवर्तित नहीं कर सकते हैं, मैं बस बाइनरी प्रतिनिधित्व (या मंटिसा + एक्सपोनेंट अलग से) को डंप करने का प्रस्ताव दूंगा। – Vlad

+5

@Vlad आप नहीं कर सकते? सभी बाइनरी अंश एक सीमित दशमलव के रूप में प्रतिनिधित्व योग्य नहीं हैं? –

उत्तर

16

आदेश में गारंटी नहीं है कि एक binary-> decimal-> द्विआधारी गोल यात्रा मूल बाइनरी मान ठीक हो, IEEE 754 की आवश्यकता है


The original binary value will be preserved by converting to decimal and back again using:[10] 

    5 decimal digits for binary16 
    9 decimal digits for binary32 
    17 decimal digits for binary64 
    36 decimal digits for binary128 

For other binary formats the required number of decimal digits is 

    1 + ceiling(p*log10(2)) 

where p is the number of significant bits in the binary format, e.g. 24 bits for binary32. 

सी में, कार्यों आप इन रूपांतरण के लिए उपयोग कर सकते हैं snprintf हैं() और strtof/strtod/strtold()।

बेशक, कुछ मामलों में भी अधिक अंक उपयोगी हो सकते हैं (नहीं, वे हमेशा "शोर" नहीं होते हैं, जैसे कि स्निपिंटफ()) के दशमलव रूपांतरण दिनचर्या के कार्यान्वयन के आधार पर। उदाहरण पर विचार करें printing dyadic fractions

+0

+1 मानक-प्रमाणित उत्तर के लिए (हालांकि एक आईईईई अनुपालन कार्यान्वयन मानते हुए, लेकिन जो भी आईईईई फ्लोट का उपयोग नहीं करता है)। –

+0

@ क्रिस्टियन राउ: इन दिनों आईईईई का उपयोग कम या ज्यादा करता है हां। हालांकि, चेतावनी यह है कि क्या आपके दशमलव रूपांतरण फ़ंक्शन सभी इनपुट के लिए सही ढंग से गोल किए गए हैं, जो शायद कम निश्चित है।लेकिन अगर आपको दशमलव प्रतिनिधित्व की आवश्यकता है, तो आप इसके बारे में ज्यादा कुछ नहीं कर सकते (अपने स्वयं के बग-मुक्त दशमलव रूपांतरणों को लागू करने के अलावा, शुभकामनाएं!)। – janneb

+0

@ क्रिस्टियन राउ, जेनब: यह सार्वभौमिक नहीं है। मुझे अभी भी कभी-कभी भूकंपीय डेटा से निपटना पड़ता है जो आईबीएम फ्लोटिंग-पॉइंट प्रारूप में उत्पन्न हुआ है! –

1

जावा में उपयोग किए जाने वाले फ़्लोटिंग-पॉइंट-टू-दशमलव रूपांतरण को अपने पड़ोसियों (अधिक या कम) से संख्या को अलग करने के लिए आवश्यक दशमलव बिंदु से कम दशमलव अंकों की कम से कम संख्या का उत्पादन करने की गारंटी है। FloatingDecimal(float) निर्माता और toJavaFormatString() विधि के लिए http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html वेतन ध्यान:

आप यहाँ से एल्गोरिथ्म कॉपी कर सकते हैं।

+7

बिल्कुल उस कोड में जहां 2800+ कोड की रेखाएं एल्गोरिदम शुरू होती हैं? – Gabe

+0

तकनीकी रूप से जीपीएल – sehe

+0

@Gabe यह कन्स्ट्रक्टर में शुरू होता है और जिस तरीके से मैं इंगित करता हूं उसमें समाप्त होता है। पूर्ण स्ट्रिंग को 'नई फ़्लोटिंगडिमल (संख्या) .toJavaFormatString() 'अभिव्यक्ति द्वारा वापस किया जाता है। – Joni

0

आप sprintf का उपयोग कर सकते हैं। मुझे यकीन है कि यह आपके सवाल का जवाब है कि क्या वास्तव में हालांकि नहीं हूँ, लेकिन वैसे भी, यहाँ नमूना कोड

#include <stdio.h> 
int main(void) 
{ 
float d_n = 123.45; 
char s_cp[13] = { '\0' }; 
char s_cnp[4] = { '\0' }; 
/* 
* with sprintf you need to make sure there's enough space 
* declared in the array 
*/ 
sprintf(s_cp, "%.2f", d_n); 
printf("%s\n", s_cp); 
/* 
* snprinft allows to control how much is read into array. 
* it might have portable issues if you are not using C99 
*/ 
snprintf(s_cnp, sizeof s_cnp - 1 , "%f", d_n); 
printf("%s\n", s_cnp); 
getchar(); 
return 0; 
} 
/* output : 
* 123.45 
* 123 
*/ 
है
+3

यह एक समझदार दृष्टिकोण है, लेकिन स्प्रिंटफ का उपयोग करने के साथ हमने पाया एक चीज यह है कि गोलाकार विभिन्न प्लेटफार्मों के लिए अलग हो सकता है। –

+0

@ रिचर्ड हाँ यू आर इस बारे में सही ... – kapilddit

3

24 * (लॉग (2)/लॉग (10)) = 7,2247199

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

24 * (लॉग (2)/लॉग (10)) = 7

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

अंतिम लेकिन कम से कम नहीं, आप अपने कार्यक्रम में खिलाए गए नंबरों की सटीकता को अनदेखा नहीं कर सकते हैं। एक अज्ञात यूरोपीय की गति को मापना 7 अंकों तक निगलना संभव नहीं है। यह लगभग 11 मीटर प्रति सेकंड, 2 अंक सबसे अच्छा है। तो उस गति पर गणना करना और परिणामस्वरूप प्रिंट करना अधिक महत्वपूर्ण अंक गैरकानूनी परिणाम उत्पन्न करते हैं जो सटीकता का वादा करते हैं जो वहां नहीं है।

+10

* किसी अन्य प्रोग्राम के अंदर उपयोग किया जाना चाहिए * => ऐसा लगता है कि आउटपुट पढ़ने वाले मानव के बारे में आपकी धारणा गलत है। –

+0

हम्म, जो वास्तव में पंजीकृत नहीं था। करने के लिए अजीब चीज। खैर, आसान फिक्स, जब तक कि एक इंसान इसे कभी नहीं देखता है, फिर अंकों को प्रिंट करें। –

+1

मुझे इससे नफरत है जब ऐसा लगता है कि मेरे दिमाग ने टेक्स्ट में एक आयात शब्द संपादित किया है: x ऐसा लगता है कि फ्रेड अंतरिक्ष खपत (और मुझे लगता है कि प्रदर्शन) के बारे में चिंतित था। –

-1
तरह

def f(a): 
    b=0 
    while a != int(a): a*=2; b+=1 
    return a, b 

कुछ (जो अजगर है) आप एक नुकसान से मुक्त रास्ते में अपूर्णांश और प्रतिपादक प्राप्त करने में सक्षम होना चाहिए के साथ

सी में, यह शायद

struct float_decomp { 
    float mantissa; 
    int exponent; 
} 

struct float_decomp decomp(float x) 
{ 
    struct float_decomp ret = { .mantissa = x, .exponent = 0}; 
    while x != floor(x) { 
     ret.mantissa *= 2; 
     ret.exponent += 1; 
    } 
    return ret; 
} 

होगा लेकिन ध्यान रखें कि अभी भी नहीं सभी मूल्यों है कि रास्ते में व्यक्त किया जा सकता हो, यह सिर्फ एक त्वरित शॉट जो पता चलना चाहिए, लेकिन शायद सुधार की जरूरत है।

+0

बिना किसी टिप्पणी के -1 के लिए यह बहुत उपयोगी है। – glglgl

2

यदि प्रोग्राम कंप्यूटर द्वारा पढ़ा जाने वाला है, तो मैं char* एलियासिंग का उपयोग करने की सरल चाल करूंगा।

  • उर्फ ​​float*char* अलियासिंग के माध्यम से एक unsigned में char*
  • प्रतिलिपि (या जो भी अहस्ताक्षरित प्रकार पर्याप्त रूप से बड़े है) करने के लिए
  • प्रिंट unsigned मूल्य

डिकोडिंग सिर्फ प्रक्रिया विपरीत हो रहा है (और अधिकांश प्लेटफ़ॉर्म पर प्रत्यक्ष reinterpret_cast का उपयोग किया जा सकता है)।

+0

निश्चित रूप से सीधे 'हस्ताक्षरित *' पर एलियासिंग भी काम करेगा? – huon

+2

और किस तरह से यह एक फ्लोट शाब्दिक देता है? बेशक आप कुछ जगहों के साथ सटीक सटीकता प्राप्त करने के लिए हमेशा बाइनरी प्रस्तुति का उपयोग कर सकते हैं, लेकिन अच्छी तरह से ... –

+0

@ क्रिस्टियन राउ: मेरा विचार प्रारंभिक आवश्यकता को चुनौती देना था कि दो कार्यक्रमों के लिए फ्लोटिंग पॉइंट नंबरों का आदान-प्रदान करने के लिए एक शाब्दिक प्रतिनिधित्व की आवश्यकता होगी। चूंकि प्रारूप सामान्यीकृत (और मानक द्वारा अनिवार्य) है, बाइनरी प्रतिनिधित्व का उपयोग पोर्टेबल (संभावित अंतराल मुद्दे पर) है। –

2

यदि आपके पास सी सी पुस्तकालय है जो सी 99 के अनुरूप है (और यदि आपके फ्लोट प्रकारों का आधार 2 है जो 2 की शक्ति है :) printf प्रारूप वर्ण %a हेक्साडेसिमल रूप में परिशुद्धता की कमी के बिना फ़्लोटिंग पॉइंट मान मुद्रित कर सकता है, और scanf और strod के रूप में उपयोगिताएं उन्हें पढ़ने में सक्षम होंगी।

1

यदि आप इन कागजात को पढ़ते हैं (नीचे देखें), तो आप पाएंगे कि कुछ एल्गोरिदम हैं जो दशमलव अंकों की न्यूनतम संख्या मुद्रित करते हैं जैसे कि संख्या को अपरिवर्तित (यानी scanf द्वारा) का पुन: व्याख्या किया जा सकता है।

चूंकि ऐसी कई संख्याएं हो सकती हैं, इसलिए एल्गोरिदम मूल बाइनरी अंश (मैंने फ्लोट वैल्यू नामित) में निकटतम दशमलव अंश भी चुना है।

एक अफ़सोस की बात है यह है कि सी