2009-11-22 13 views
5

में मैं C Primer Plus किताब पढ़ रही है और यह उदाहरणलांग डबल सी

#include <stdio.h> 
int main(void) 
{ 
    float aboat = 32000.0; 
    double abet = 2.14e9; 
    long double dip = 5.32e-5; 

    printf("%f can be written %e\n", aboat, aboat); 
    printf("%f can be written %e\n", abet, abet); 
    printf("%f can be written %e\n", dip, dip); 

    return 0; 
} 

गया के बाद मैं अपने मैकबुक पर इस भाग गया मैं उत्पादन पर काफी झटका लगा है:

32000.000000 can be written 3.200000e+04 
2140000000.000000 can be written 2.140000e+09 
2140000000.000000 can be written 2.140000e+09 

तो मैंने गोल देखा और पाया कि लंबे समय तक प्रदर्शित करने के लिए सही प्रारूप %Lf का उपयोग करना है। हालांकि मैं अभी भी नहीं समझ सकता कारण है कि मैं बजाय मैं क्या हो गया, जब मैं Cygwin, उबंटू और iDeneb जो मोटे तौर पर

-1950228512509697486020297654959439872418023994430148306244153100897726713609 
013030397828640261329800797420159101801613476402327600937901161313172717568.0 
00000 can be written 2.725000e+02 

कोई भी विचार है पर यह भाग गया के दोहरे abet मूल्य है?

+0

क्या आप वाकई कि कोड केवल एक था कर रहे हैं? मैंने बस इसे अपने मैकबुक - मैकोज़ एक्स 10.5.8 (जीसीसी 4.0.1) पर चलाया और अपना साइगविन परिणाम प्राप्त किया। –

+0

हां मैंने अभी इसे फिर से जांच लिया है। Btw मैं MacOS एक्स 10.6.2 (जीसीसी 4.2.1) चल रहा हूँ – reubensammut

+0

असल में मैं मैक पर उम्मीद अतर्कसंगत जवाब मिलता है। पेचीदा। मेरे निष्पादन योग्य पर 'otool -L' चलाना मुझे बताता है कि यह /usr/lib/libSystem.B.dylib संस्करण 111.1.4 के विरुद्ध चल रहा है; वह पुस्तकालय है जो 'printf' प्रदान करता है। यदि आपके पास उस लाइब्रेरी का एक ही संस्करण है, तो आपको वही जवाब मिलना चाहिए। –

उत्तर

7

ओएसएक्स पर कन्वर्टिंग कॉलिंग को देखने की कोशिश करें, जो इसे समझा सकता है। (या ढेरों पर)

मैं संकलक अनुमान लगा रहा हूँ गुजरता ढेर (या एक एफपीयू रजिस्टर में) पर पहले long double पैरामीटर, और CPU रजिस्टरों में पहली double पैरामीटर। किसी भी तरह से, वे विभिन्न स्थानों में पारित कर रहे हैं। तो जब तीसरा कॉल किया जाता है, तो दूसरी कॉल का मूल्य अभी भी झूठ बोल रहा है (और कैली इसे उठाता है)। लेकिन यह सिर्फ एक अनुमान है।

+0

+1 मानसिक डिबगिंग :) – Andomar

3

शायद 64-बिट एबीआई इस तरह से भिन्न है कि printf% f तर्कों की तुलना में% f तर्कों को पूरी तरह से अलग स्थान पर देखता है।

यह सच है कि यह देखने के लिए असेंबली आउटपुट (gcc -S) को देखने का प्रयास करें।

+0

मैं विधानसभा पर एक नजर है और देखते हैं अगर यह मामला है, हालांकि यह कुछ समय लग सकता है क्योंकि मैं विशेष रूप से x86-64 एक – reubensammut

4

C Standard Library के printf() समारोह एक variadic function का एक उदाहरण है, कि एक जो तर्क की विभिन्न संख्या ले सकता है। जिस तरीके से सी भाषा इस पर लागू होती है, बुलाया गया कार्य पता होना चाहिए कि किस प्रकार के तर्क पारित किए गए थे ताकि क्रम में उन्हें सही तरीके से व्याख्या की जा सके। यही कारण है कि आप एक प्रारूप स्ट्रिंग पास करते हैं, ताकि printf() प्रिंट करने के लिए डेटा को सही ढंग से समझ सके।

एक variadic समारोह को गलत ढंग से तर्क यह करने के लिए पारित कर दिया समझता है, तो सी मानक निर्दिष्ट करता है कि व्यवहार अपरिभाषित है, वह यह है कि कुछ भी (C89 मानक पैरा 4.8.1.2) हो सकता है। आपके मामले में, जहां आप printf() पर गैर मिलान वाले प्रारूपों और मानों में गुजर रहे हैं, वही हो रहा है। हालांकि, अगर आपके पास एक सभ्य कंपाइलर है और आपका चेतावनी स्तर कुछ समझदार हो गया है, तो आपको इसके बारे में संकलन समय पर चेतावनी दी जानी चाहिए। उदाहरण के लिए, Cygwin पर, मैं मिलता है:

$ make go 
cc -g -W -Wall -Wwrite-strings -ansi -pedantic go.c -o go 
go.c: In function `main': 
go.c:10: warning: double format, long double arg (arg 2) 
go.c:10: warning: double format, long double arg (arg 3) 
go.c:10: warning: double format, long double arg (arg 2) 
go.c:10: warning: double format, long double arg (arg 3) 
$ 

कारण है कि आप विशेष रूप से आप क्या देख रहे हैं पाने के लिए के रूप में, इस विशेष कार्यान्वयन पर निर्भर करेगा। व्यावहारिक रूप से, होने की संभावना क्या है कि printf() का आपका विशेष कार्यान्वयन के पहले भाग को double के रूप में व्याख्या कर रहा है और उस विशिष्ट बिट पैटर्न से संबंधित मान मुद्रित कर रहा है। हालांकि, मानक राज्यों के रूप में, यह जो कुछ भी पसंद करता है वह कर सकता है।

+0

साथ विधानसभा में वास्तव में विश्वास है नहीं कर रहा हूँ इसके अलावा कि variadic साथ ध्यान देंगे फ़ंक्शंस, 'फ्लोट' पैरामीटर को हमेशा प्रचारित किया जाता है और 'डबल' के रूप में पारित किया जाता है। इंटीग्रल पैरामीटर 'char' और' short' को 'int' (या' unsigned int') में पदोन्नत किया जाता है। – tomlogic

+0

@tomlogic: कश्मीर एंड आर variadic कार्यों में एक ही प्रकार के लिए सभी फ्लोटिंग प्वाइंट मूल्यों coercing के लिए एक अच्छा कारण नहीं था; एएनएसआई सी को प्रोटोटाइप को फ्लोटिंग-पॉइंट प्रकार को निर्दिष्ट करने की इजाजत देनी चाहिए, जिसमें सभी फ़्लोटिंग-पॉइंट मान परिवर्तित किए जाएंगे। 80-बिट फ्लोटिंग-पॉइंट का उपयोग करके कंप्यूटेशंस करने वाले मशीनों के लिए कई कंपाइलर्स ने 'लंबी डबल' 64 बिट्स बनाकर और 80-बिट प्रकार प्रदान करके ऐसी सुविधा की कमी के आसपास काम किया, इस प्रकार फ्लोटिंग-पॉइंट गणित का अवक्रमण होता है। इस दिन जारी है। – supercat

1

मैं सी प्राइमर प्लस पढ़ रहा हूं, जैसा कि मैंने एक ही चीज़ देखी है। देखें कि मैंने तीसरे printf कथन के लिए प्रारूप विनिर्देशों को कैसे बदला।

#include <stdio.h> 
#include <inttypes.h> 

int main(void){ 

    float aboat = 320000.0; 
    double abet = 2.214e9; 
    long double dip = 5.32e-5; 

    printf("%f can be written %e\n", aboat, aboat); 
    printf("%f can be written %e\n", abet, abet); 
    printf("%Lf can be written %Le\n", dip, dip); 

    return 0; 
} 

परिणाम long double बजाय %lf या %f के लिए %LF के रूप में प्रारूप विनिर्देशक

320000.000000 can be written 3.200000e+05 
2214000000.000000 can be written 2.214000e+09 
0.000053 can be written 5.320000e-05 
3

उपयोग विनिर्देशक बदलने के बाद। %LF का हमेशा %lf से भिन्न अर्थ है।

#include <stdio.h> 
int main(void) 
{ 
    float aboat = 32000.0; 
    double abet = 2.14e9; 
    long double dip = 5.32e-5L; 

    printf("%f can be written %e\n", aboat, aboat); 
    printf("%f can be written %e\n", abet, abet); 
    printf("%LF can be written %LE\n", dip, dip); 

    return 0; 
} 

आउटपुट:

The output; transcript below

32000.000000 can be written 3.200000e+04 
2140000000.000000 can be written 2.140000e+09 
0.000053 can be written 5.320000E-05 
+0

यह एक अच्छा जवाब है। कृपया और पोस्ट करें! – wizzwizz4

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