दो इंट को विभाजित करने पर डबल को असाइन करने पर सही मान क्यों नहीं मिलता है?


110

कैसे निम्नलिखित स्निपेट में आते हैं

int a = 7;
int b = 3;
double c = 0;
c = a / b;

c2.3333 के बजाय मान 2 होता है, जैसा कि कोई अपेक्षा करता है। यदि aऔर bयुगल हैं, तो उत्तर 2.333 हो जाता है। लेकिन निश्चित रूप से क्योंकि c पहले से ही एक डबल है यह पूर्णांक के साथ काम करना चाहिए था?

तो कैसे int/int=doubleकाम नहीं करता है?


जवाबों:


161

इसका कारण यह है कि आप पूर्णांक विभाजन संस्करण का उपयोग कर रहे हैं operator/, जो 2 intएस लेता है और एक रिटर्न देता है intdoubleसंस्करण का उपयोग करने के लिए , जो एक रिटर्न देता है double, कम से कम किसी एक को intस्पष्ट रूप से एक में डाला जाना चाहिए double

c = a/(double)b;

9
मैं स्पष्ट रूप से दोनों परिवर्तित करने के लिए पसंद करेंगे aऔर bकरने के लिए doubleबस स्पष्टता के लिए, लेकिन यह वास्तव में बात नहीं करता है।
जॉन डिब्लिंग

31
चूंकि प्रश्न C ++ का टैग है, इसलिए मैं C कास्ट के बजाय static_cast <> देखना पसंद करूंगा।
मार्टिन

16
व्यक्तिगत रूप से, मुझे लगता है कि सी शैली की जातियां स्पष्ट हैं (अधिकांश अन्य भाषाओं में कास्टिंग सी शैली में की जाती है)। static_cast<>हमेशा मुझे लंबी हवा लगती थी। आदिम के मामले में, वास्तव में कोई खतरा नहीं है static_cast<>और reinterpret_cast<>मिलाया जाता है।
चाड ला गार्डिया

6
@ टक्स-डी: अंकगणित जातियों के लिए? मैं static_castइस मामले में बचना पसंद करूंगा और इसके बजाय सी-स्टाइल कास्ट का उपयोग करूंगा । यहाँ C ++ शैली की कास्ट का उपयोग करने में कोई लाभ नहीं है और वे कोड को C- शैली के कलाकारों की तुलना में बहुत अधिक अव्यवस्थित करते हैं। अंकगणित कास्ट बिल्कुल वैसा ही प्रसंग है जहाँ सी-शैली की कास्ट पूरी तरह से उपयुक्त होती है और वास्तव में अन्य जातियों की तुलना में अधिक उपयुक्त होती है।
एएनटी

19
कभी-कभी आप "नो सी-स्टाइल-कास्ट" लोगों को लिखकर आगे बढ़ा सकते हैं double(b)। वे हमेशा महसूस नहीं करते हैं कि यह एक रूपांतरण है, क्योंकि यह एक स्पष्ट रचनाकार कॉल के समान दिखता है।
स्टीव जेसोप

12

यह रहा:

क) विभाजित दो intएस पूर्णांक विभाजन हमेशा करता है। तो a/bआपके मामले का परिणाम केवल एक हो सकता है int

आप रखना चाहते हैं aऔर bके रूप में intहै, अभी तक उन्हें पूरी तरह से विभाजित है, तो आप दोगुना करने के लिए उनमें से कम से कम एक कास्ट करना होगा: (double)a/bया a/(double)bया (double)a/(double)b

बी) cएक है double, इसलिए यह असाइनमेंट पर एक मूल्य को स्वीकार कर सकता है: स्वचालित रूप से परिवर्तित और असाइन किया गया है ।intintdoublec

ग) याद रखें कि असाइनमेंट पर, पहले के नियम के अनुसार अभिव्यक्ति =की गणना की जाती है (नियम के अनुसार (ए) ऊपर, और चर के बाईं ओर के बिना ) और फिर (के अनुसार) के बाईं ओर चर को सौंपा b) ऊपर)। मेरा मानना ​​है कि यह चित्र को पूरा करता है।==


11

बहुत कम अपवादों के साथ (मैं केवल एक के बारे में सोच सकता हूं), C ++ अभिव्यक्ति के पूरे अर्थ (या उप-अभिव्यक्ति) को अभिव्यक्ति से ही निर्धारित करता है। आप अभिव्यक्ति के परिणामों के साथ क्या करते हैं इससे कोई फर्क नहीं पड़ता। आपके मामले में, अभिव्यक्ति में a / b, doubleदृष्टि में नहीं है ; सब कुछ है int। इसलिए कंपाइलर पूर्णांक विभाजन का उपयोग करता है। केवल एक बार इसका परिणाम होने पर यह विचार करता है कि इसके साथ क्या करना है, और इसे किस रूप में बदलना है double


3
एक अपवाद जो मैं सोच सकता हूं कि एक पॉइंटर लेते समय एक फ़ंक्शन अधिभार चुनना है - यह &funcnameनिर्भर करता है कि आप इसे किस प्रकार के लिए डालते हैं।
स्टीव जेसोप

2
@ जेस जेसप यही एकमात्र अपवाद है जो मैं भी सोच सकता हूं। (लेकिन मानक के आकार और जटिलता को देखते हुए, मैं कसम नहीं लेना चाहूंगा कि मैंने कोई भी चूक नहीं की है।)
जेम्स कान्जे

6

cएक doubleचर है, लेकिन इसे सौंपा जाने वाला intमूल्य एक मूल्य है क्योंकि यह दो intएस के विभाजन के परिणामस्वरूप होता है , जो आपको "पूर्णांक विभाजन" (शेष को छोड़ना) देता है। तो लाइन में क्या होता c=a/bहै

  1. a/b मूल्यांकन किया जाता है, एक अस्थायी प्रकार का निर्माण int
  2. अस्थायी का मान cटाइप करने के लिए रूपांतरण के बाद सौंपा गया है double

का मान a/bउसके संदर्भ (असाइनमेंट double) के संदर्भ के बिना निर्धारित किया जाता है ।


6

जब आप दो पूर्णांकों को विभाजित करते हैं, तो परिणाम एक पूर्णांक होगा, इस तथ्य के बावजूद कि आप इसे एक डबल में संग्रहीत करते हैं।


5

सी ++ भाषा में सबएक्सप्रेससन का परिणाम आसपास के संदर्भ (कुछ दुर्लभ अपवादों) के साथ कभी भी प्रभावित नहीं होता है। यह उन सिद्धांतों में से एक है जिसका भाषा ध्यान से पालन करती है। अभिव्यक्ति c = a / bमें एक स्वतंत्र उपसक्रियता शामिल होती है a / b, जिसे उस उपप्राण के बाहर किसी भी चीज़ से स्वतंत्र रूप से व्याख्या की जाती है। भाषा का ध्यान नहीं है कि आप बाद में परिणाम को असाइन करेंगे doublea / bपूर्णांक विभाजन है। और कुछ भी मायने नहीं रखता। आप इस सिद्धांत को भाषा विनिर्देश के कई कोनों में देखेंगे। कि C ++ (और C) कैसे काम करता है।

एक अपवाद का एक उदाहरण जिसका मैंने ऊपर उल्लेख किया है, फ़ंक्शन पॉइंटर असाइनमेंट / फ़ंक्शन ओवरलोडिंग के साथ स्थितियों में आरंभीकरण है

void foo(int);
void foo(double);

void (*p)(double) = &foo; // automatically selects `foo(fouble)`

यह एक संदर्भ है जहां एक असाइनमेंट / इनिशियलाइज़ेशन के बाएँ हाथ की ओर राइट-साइड के व्यवहार को प्रभावित करता है। (इसके अलावा, संदर्भ-से-सरणी आरंभीकरण प्रकार प्रकार के क्षय को रोकता है, जो समान व्यवहार का एक और उदाहरण है।) अन्य सभी मामलों में दाहिने हाथ की ओर बाईं ओर की ओर पूरी तरह से नजरअंदाज करती है।


4

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


2

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

एक ही प्रकार (पूर्णांक, युगल, आदि) की दो संख्याओं को विभाजित करने पर परिणाम हमेशा एक ही प्रकार का होगा (इसलिए 'int / int' हमेशा int में परिणाम देगा)।

इस स्थिति में आपके पास गणना के बादdouble var = integer result पूर्णांक परिणाम दोगुना हो जाता है जिस स्थिति में भिन्नात्मक डेटा पहले से ही खो जाता है। (अधिकांश भाषाएं बिना किसी अपवाद या त्रुटि को बढ़ाए गलत प्रकार को रोकने के लिए यह कास्टिंग करेंगी)।

यदि आप परिणाम को एक दोहरे के रूप में रखना चाहते हैं तो आप एक ऐसी स्थिति बनाना चाहते हैं जहां आपके पास हो double var = double result

ऐसा करने का सबसे आसान तरीका है कि किसी समीकरण के दाईं ओर अभिव्यक्ति को डबल करने के लिए मजबूर किया जाए:

c = a/(double)b

एक पूर्णांक और एक डबल के बीच विभाजन पूर्णांक को डबल में कास्टिंग करेगा (ध्यान दें कि जब गणित कर रहे हैं, तो कंपाइलर अक्सर सबसे विशिष्ट डेटा प्रकार को "अपकास्ट" करेगा यह डेटा हानि को रोकने के लिए है)।

aऊपर उठने के बाद, एक डबल के रूप में हवा होगी और अब आपके पास दो युगल के बीच विभाजन होगा। यह वांछित विभाजन और असाइनमेंट बनाएगा।

फिर, कृपया ध्यान दें कि यह भाषा विशिष्ट है (और यहां तक ​​कि संकलक विशिष्ट भी हो सकती है), हालांकि लगभग सभी भाषाएं (निश्चित रूप से सभी जो मैं अपने सिर के ऊपर से सोच सकता हूं) इस उदाहरण को समान रूप से मानते हैं।


इस प्रश्न को टैग किया गया है [C ++], और C ++ मानक यह बताता है कि यह कैसे कार्य करता है। निश्चित नहीं है कि आप "भाषा विशिष्ट" से क्या मतलब है और यह निश्चित रूप से संकलक-विशिष्ट नहीं है, यह मानते हुए कि कोई संकलक नहीं लगे हुए हैं।
जॉन डिब्लिंग

इसके अलावा यह कहना गलत है कि "डबल var = पूर्णांक परिणाम जो डबल var को int में डाल देता है"। डबल को इंट में नहीं डाला गया है। इंट रिजल्ट को डबल में बदला जाता है।
जॉन डिब्लिंग

मैं संकलक एक्सटेंशन की संभावना के लिए अनुमति दे रहा था (मेरे पास वास्तव में यह मुद्दा था एक बार जहां मेरा वातावरण परिणामों को "गलत-कास्टिंग" कर रहा था और मैं इसका पता नहीं लगा सका)। और परिणाम भाषा विशिष्ट है क्योंकि कुछ भाषाओं में समान कास्टिंग नियमों का पालन नहीं होता है। मुझे नहीं लगा कि यह एक C ++ विशिष्ट टैग था। आप "डबल var = पूर्णांक परिणाम" टिप्पणी के बारे में सही हैं। को प्रतिबिंबित करने के लिए संपादित। धन्यवाद!
मैथ्यू सदनमना

0

महत्वपूर्ण बात यह है कि गणना के तत्वों में से एक फ्लोट-डबल प्रकार है। फिर एक डबल परिणाम प्राप्त करने के लिए आपको इस तत्व को डालना होगा जैसे नीचे दिखाया गया है:

c = static_cast<double>(a) / b;

या c = / a / static_cast (b);

या आप इसे सीधे बना सकते हैं ::

c = 7.0 / 3;

ध्यान दें कि एक पूर्णांक द्वारा फ्लोट-डबल प्रकार के विभाजन को इंगित करने के लिए गणना के तत्वों में से एक में '.0' होना चाहिए। अन्यथा, c वैरिएबल डबल होने के बावजूद, परिणाम शून्य भी होगा।


आपका जवाब क्या लाता है कि अन्य 9 जवाबों में से कोई भी पहले से मौजूद नहीं है?
bolov
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.