2012-01-18 5 views
15

स्वयं को सिखा रहा है और यह खोज रहा है कि जब मैं एक अस्थायी रूपांतरण के लिए समीकरण करता हूं तो यह तब तक काम नहीं करेगा जब तक कि मैं अंश को दशमलव में परिवर्तित नहीं करता। यानी,दशमलव के बजाय विभाजन का परिणाम शून्य में क्यों होता है?

tempC=(.555*(tempF-32)) काम करेगा लेकिन tempC=((5/9)*(tempF-32)) काम नहीं करेगा।

क्यों?
सी प्राइमर प्लस के अनुसार यह काम करना चाहिए क्योंकि मैं tempC और tempF दोनों के लिए फ्लोट का उपयोग कर रहा हूं।

उत्तर

16

ऐसा लगता है कि आप दूसरे मामले में पूर्णांक प्रभाग है:

tempC=((5/9)*(tempF-32)) 

5/9 शून्य करने के लिए छोटा हो जाएगा।

कि ठीक करने के लिए, आप उनमें से एक एक फ्लोटिंग प्वाइंट प्रकार बनाने की जरूरत है:

tempC=((5./9.)*(tempF-32)) 
+2

यह छंटनी नहीं है, हालांकि, गोल नहीं है। – jmkeyes

+0

शब्दावली फिक्स के लिए धन्यवाद। :) – Mysticial

+0

दोह! धन्यवाद ... अब समझ में आता है। मैंने कुछ उदाहरणों में दशमलव के साथ देखा लेकिन पैसा कम नहीं हुआ। आप सभी को धन्यवाद! –

0

आप कोष्ठक में 5/9 डालें, तो यह पहली गणना की जाएगी, और के बाद से उन दो पूर्णांक हैं, यह पूर्णांक विभाजन द्वारा किया जाएगा और परिणाम अभिव्यक्ति के बाकी होने से पहले 0 होगा।

आप इतना है कि रूपांतरण फ्लोट करने के लिए पहली बार होता है कि आपकी अभिव्यक्ति पुनर्व्यवस्थित कर सकते हैं:

tempC=((5/9)*(tempF-32));tempC=(5*(tempF-32))/9;

या ज़ाहिर है, दूसरों के रूप में कहते हैं, चल बिन्दु स्थिरांक का उपयोग करें।

+0

भले ही वे कंस्ट्रैसिस में नहीं थे, फिर भी उन्हें पूर्णांक के रूप में मूल्यांकन किया जा सकता था। इस अभिव्यक्ति के मूल्यांकन का क्रम सी में अनिर्दिष्ट व्यवहार है, संकलक बाएं से दाएं या दाएं से बाएं का मूल्यांकन करना चुन सकता है, और आप यह नहीं जान सकते कि मूल्यांकन का कौन सा क्रम लागू होता है। – Lundin

+1

पूरी तरह से सच नहीं है। कंस्ट्रैसिस का असर पड़ता है! यदि आप सुनिश्चित करते हैं कि पहली गणना जो एक फ्लोट में होती है, तो शेष अभिव्यक्ति पूर्णांक पर वापस नहीं आ जाएगी। मैंने अपना जवाब यह दिखाने के लिए बढ़ाया है कि मेरा क्या मतलब है। –

+0

पुनर्लेखन उदाहरण कोष्ठक को हटाने के बराबर नहीं है, आपने जानबूझकर मूल्यांकन के क्रम को बदल दिया है। 'tempC = 5/9 * (tempF-32); 'कोष्ठक के साथ हटाया गया उदाहरण है। यह उदाहरण इच्छित परिणाम दे सकता है या नहीं दे सकता है, इस पर निर्भर करता है कि संकलक बाएं से दाएं या दाएं से बाएं का मूल्यांकन करता है - यह अनिर्दिष्ट व्यवहार पर निर्भर करता है। – Lundin

1

5/9 एक पूर्णांक अभिव्यक्ति है, क्योंकि यह 0 तक छोटा हो जाता है। आपके कंपाइलर को आपको इसके बारे में चेतावनी देना चाहिए, अन्यथा आपको चेतावनियां सक्षम करने में देखना चाहिए।

+3

मैं वास्तव में नहीं देखता कि इसे चेतावनी क्यों दी जानी चाहिए। संकलक के बारे में बताने का कोई तरीका नहीं है कि कोई व्यक्ति अपने पूर्णांक स्थिरांक को किस मूल्य के लिए चाहता है। – Lundin

+1

@ लुंडिन: यही कारण है कि यह एक (pedantic) चेतावनी होगी। यदि निरंतर पूर्णांक अभिव्यक्ति शून्य उत्पन्न करती है, तो यह शून्य होनी चाहिए या एक निरीक्षण था। – Necrolis

+0

जरूरी नहीं है, ऐसे कई मामले हो सकते हैं जहां आप परिणाम 0 के साथ निरंतर अभिव्यक्ति चाहते हैं। उदाहरण के लिए 'परिणाम = SOME_CONSTANT & MASK;' शून्य का बहुत अच्छा परिणाम हो सकता है। आइए कहें कि आपके पास विभिन्न मास्क के साथ कोड पर समान मास्किंग ऑपरेशंस हैं। आप तब सैकड़ों चेतावनियां नहीं चाहते हैं, आपको केवल इसलिए दंडित क्यों किया जाना चाहिए क्योंकि आप जेनेरिक, संगत कोड को बिना किसी जादू संख्या के लिखते हैं? – Lundin

2

जब आप 5/9, 5 और 9 कर दोनों पूर्णांकों और पूर्णांक विभाजन होता है। पूर्णांक विभाजन का परिणाम एक पूर्णांक है और यह दो ऑपरेटरों का अंश है। तो, 5/9 के मामले में भाग्य 0 है और चूंकि आप 0 से गुणा करते हैं, इसलिए tempC 0 हो जाता है। पूर्णांक विभाजन नहीं होने के लिए, कम से कम दो ऑपरेटरों में से एक float होना चाहिए।

उदा। यदि आप 5.0/9 या 5/9.0 या 5.0/9.0 का उपयोग करते हैं, तो यह अपेक्षित काम करेगा।

5

अन्य ने पहले ही आपको बताया है, 5 और 9 दोनों पूर्णांक हैं और यही कारण है कि परिणाम छोटा हो जाता है।

मैं क्या वास्तव में लाइनों के बीच पर चला जाता है की गहरी समझ के लिए एक स्पष्टीकरण जोड़ देगा:

double tempC; 
double tempF; 
tempC = (5/9) * (tempF-32); // removed unnecessary parenthesis 

निर्भर करता है जो मूल्यांकन की आदेश, पर बाएँ-से-दाएँ या दाएँ-से-बाएँ, कि आपका विशिष्ट कंपाइलर उपयोग करता है, यह या तो उप-अभिव्यक्ति (5/9) या (tempF-32) का मूल्यांकन शुरू कर देगा।

आप नहीं जानते कि इनमें से कौन सा मूल्यांकन किया गया है! क्योंकि मूल्यांकन का क्रम सी में अनिर्दिष्ट व्यवहार है, जिसका अर्थ यह है कि संकलक बिना किसी दस्तावेज़ के इसे कर सकता है। इसलिए, किसी को मूल्यांकन के आदेश पर भरोसा कोड नहीं लिखना चाहिए, या यह पोर्टेबल और संभवतः गलत नहीं होगा।


आइए मान लें कि एक विशिष्ट कंपाइलर बाएं से दाएं मूल्यांकन का उपयोग करता है।

  • ऑपरेटर प्राथमिकता नियम सी का निर्धारण करता है कि मूल्यांकन कहां शुरू होता है। कोष्ठक ऑपरेटर सी में सर्वोच्च प्राथमिकता है, इसलिए संकलक सामने वाले पहले कोष्ठक की सामग्री का मूल्यांकन करके शुरू होगा।
  • इसलिए यह अभिव्यक्ति (5/9) से शुरू होगा।
  • कंपाइलर प्रत्येक ऑपरेंड के प्रकार की जांच करता है।
  • इस मामले में वे निरंतर पूर्णांक अक्षर दोनों हैं। सीजर int सी
  • दोनों ऑपरेटरों के लिए हमेशा एक ही प्रकार के होते हैं, इसलिए कोई अंतर्निहित प्रकार रूपांतरण की आवश्यकता नहीं होती है।
  • गणना int प्रकार पर की जाती है और परिणाम int है।

    tempC = (int)0 * (tempF-32);

    • संकलक तो मूल्यांकन करता है (tempF-32):

    तो अब अभिव्यक्ति अब मूल्यांकन किया जाता है।

  • ऑपरेटरों के प्रकार double और int हैं। वे एक ही प्रकार के नहीं हैं।
  • लागू प्रकार के रूपांतरण होते हैं। इस मामले में कुछ संतुलन कहा जाता है (औपचारिक रूप से सामान्य अंकगणितीय रूपांतरण कहा जाता है)।
  • संतुलन नियम कहते हैं कि यदि एक प्रकार डबल है और दूसरा कुछ और है, तो दूसरे प्रकार को डबल में परिवर्तित किया जाना चाहिए।
  • निहित प्रकार रूपांतरण के बाद अभिव्यक्ति अब (double)tempF - (double)32.0 के बराबर है। इसका परिणाम गणना double प्रकार के एक अस्थायी, अदृश्य चर में गणना और संग्रहीत किया जाता है। यह अदृश्य चर एक सीपीयू रजिस्टर या ढेर पर संग्रहीत है।

अब अभिव्यक्ति के रूप में वर्णित किया जा सकता

tempC = (int)result1 * (double)result2;

जहां "result1" 0 और "result2" है tempF का परिणाम है - 32.0।

  • संकलक तब इस नई अभिव्यक्ति का मूल्यांकन करता है। यह int और double पाता है।
  • फिर, संतुलन होता है और int को दो बार परिवर्तित कर दिया जाता है।
  • गुणा दो युगल पर किया जाता है, और परिणाम एक डबल है।
  • परिणाम अभी तक एक और अस्थायी, अदृश्य चर में संग्रहीत है।

tempC = (double)result3;

  • संकलक इस नई अभिव्यक्ति मूल्यांकन करता है।यह पता चलता है कि एक डबल डबल के अंदर बचाया जाना चाहिए। यह कोई समस्या नहीं है, इसलिए कोई अंतर्निहित रूपांतरण की आवश्यकता नहीं है। "परिणाम 3" tempC में संग्रहीत है।
+4

उप-अभिव्यक्तियों का मूल्यांकन करने का आदेश यहां कोई फर्क नहीं पड़ता है, क्योंकि न तो कोई दुष्प्रभाव है। – aschepler

+1

मूल्यांकन का आदेश केवल तभी मायने रखता है जब आपने इसे इस तरह लिखा: '5/9 * (tempF-32) 'अब सभी अनावश्यक कोष्ठक हटा दिए गए हैं। TempF "बाहरी" से मूल्यांकन एक डबल उपज होगा। यदि आप '(5/9) * कुछ भी डालते हैं, तो यह हमेशा' 0' होगा, जब तक कि कुछ कंपाइलर इस तरह की अभिव्यक्ति को जादुई रूप से ऊपर नहीं डालेगा, जो शायद मानक के खिलाफ भी होगा, लेकिन मैं इस पर शर्त नहीं लगाऊंगा। – luk32

2

5/9 एक पूर्णांक विभाजन एक फ़्लोटिंग पॉइंट डिवीजन नहीं है। यही कारण है कि आप गलत परिणाम प्राप्त कर रहे हैं।

5 या 9 फ्लोटिंग पॉइंट वेरिएबल बनाएं और आपको सही उत्तर मिल जाएगा।

5.0/9 या 5/9.0

+0

सहमत हुए। 'एफ' को स्थिरांक को फ़्लोटिंग पॉइंट को इंगित करने के लिए हमेशा अच्छा अभ्यास करना भी अच्छा अभ्यास है। इसी प्रकार अप्रयुक्त पूर्णांक स्थिरांक के लिए 'u' – Andrew

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