क्योंकि फ्लोट एक छोटा डबल नहीं है, और पूर्णांक एक फ्लोट (या इसके विपरीत) नहीं है।
सभी int
मानों में long
मान पर 1: 1 मैपिंग है। float
और double
के लिए यह भी सच नहीं है - फ्लोटिंग पॉइंट ऑपरेशंस इस तरह से मुश्किल हैं। उल्लेख नहीं है कि इंट-फ्लोट रूपांतरण मुक्त नहीं हैं - स्टैक/रजिस्टर में 1 बाइट मान को धक्का देने के विपरीत; दोनों आईएल कोड न केवल दोनों दृष्टिकोणों द्वारा उत्पादित x86-64 कोड देखें। आईएल कोड का आकार अनुकूलन में विचार करने का एकमात्र कारक नहीं है।
यह decimal
के विपरीत है, जो वास्तव में बेस-2 दशमलव फ़्लोटिंग पॉइंट नंबर की बजाय आधार -10 दशमलव संख्या है। वहाँ 20M
20
और इसके विपरीत करने के लिए पूरी तरह से नक्शे, तो संकलक इस फेंकना करने के लिए स्वतंत्र है:
IL_0000: ldc.i4.s 0A
IL_0002: newobj System.Decimal..ctor
एक ही दृष्टिकोण बस द्विआधारी चल बिन्दु संख्या के लिए सुरक्षित (या सस्ते) नहीं है।
आपको लगता है कि दोनों दृष्टिकोण आवश्यक रूप से सुरक्षित हैं, क्योंकि इससे कोई फर्क नहीं पड़ता कि हम एक पूर्णांक शाब्दिक ("एक स्ट्रिंग") से संकलन समय में एक डबल मान में रूपांतरण करते हैं या हम करते हैं या नहीं आईएल में
ECMA CLR कल्पना, III.1.1.1:
चल बिन्दु संख्या (स्टैटिक्स, सरणी तत्वों के लिए मेमोरी स्थान, लेकिन यह बस नहीं मामला है, विनिर्देश डाइविंग का खुलासा का एक सा रूप है और कक्षाओं के क्षेत्र) निश्चित आकार के हैं। समर्थित भंडारण आकार float32 और float64 हैं। हर जगह (मूल्यांकन स्टैक पर, तर्क के रूप में, वापसी प्रकार के रूप में, और स्थानीय चर के रूप में) फ़्लोटिंग-पॉइंट संख्याओं को एक आंतरिक फ़्लोटिंग-पॉइंट प्रकार का उपयोग करके दर्शाया जाता है। इस तरह के प्रत्येक उदाहरण में, परिवर्तनीय या अभिव्यक्ति का नाममात्र प्रकार या तो फ्लोट 32 या फ्लोट 64 है, लेकिन इसका मान अतिरिक्त सीमा और/या परिशुद्धता के साथ आंतरिक रूप से प्रदर्शित किया जा सकता है।
चीजों को कम रखने के लिए, आइए फ़्लोट 64 वास्तव में 4 बाइनरी अंकों का उपयोग करते हैं, जबकि कार्यान्वयन परिभाषित फ्लोटिंग प्रकार (एफ) 5 बाइनरी अंकों का उपयोग करता है। हम एक पूर्णांक शाब्दिक रूपांतरित करना चाहते हैं जो एक बाइनरी प्रतिनिधित्व होता है जो चार अंकों से अधिक है। अब की तुलना में यह कैसे व्यवहार करने के लिए जा रहा है:
ldc.r8 0.1011E2 ; expanded to 0.10110E2
ldc.r8 0.1E2
mul ; 0.10110E2 * 0.10000E2 == 0.10110E3
conv.r8
एफ में बदलता है, float64 नहीं। इसलिए हम वास्तव में मिलता है:
ldc.i4.s theSameLiteral
conv.r8 ; converted to 0.10111E2
mul ; 0.10111E2 * 0.10000E2 == 0.10111E3
उफ़ :)
अब, मैं यकीन है कि यह किसी भी उचित मंच पर 0-255 की श्रेणी में एक पूर्णांक के साथ होने जा रहा नहीं कर रहा है कर रहा हूँ। लेकिन चूंकि हम सीएलआर विनिर्देश के खिलाफ कोडिंग कर रहे हैं, हम उस धारणा को नहीं बना सकते हैं। जेआईटी कंपाइलर कर सकता है, लेकिन यह बहुत देर हो चुकी है। भाषा संकलक दोनों को समकक्ष समझा सकता है, लेकिन सी # विनिर्देशन नहीं करता है - double
स्थानीय को फ्लोट 64 माना जाता है, एफ नहीं। यदि आप चाहें तो आप अपनी खुद की भाषा बना सकते हैं।
किसी भी मामले में, आईएल जेनरेटर वास्तव में ज्यादा अनुकूलित नहीं करते हैं। यह अधिकांश भाग के लिए जेआईटी संकलन के लिए छोड़ दिया गया है। यदि आप एक अनुकूलित सी # -आईएल कंपाइलर चाहते हैं, तो एक लिखें - मुझे संदेह है कि प्रयास को वारंट करने के लिए पर्याप्त लाभ है, खासकर यदि आपका एकमात्र लक्ष्य आईएल कोड छोटा बनाना है। अधिकांश आईएल बाइनरी पहले से ही समकक्ष देशी कोड की तुलना में काफी छोटे हैं।
मेरी मशीन पर चलने वाले वास्तविक कोड के लिए, दोनों दृष्टिकोण वास्तव में उसी x86-64 असेंबली के परिणामस्वरूप डेटा सेगमेंट से डबल सटीक मान लोड करते हैं। जेआईटी आसानी से इस अनुकूलन को कर सकता है, क्योंकि यह जानता है कि कोड वास्तव में किस आर्किटेक्चर पर चल रहा है।
रोज़लिन इसे या तो –
अनुकूलित नहीं करता है आपका अनुकूलन एक नहीं है, क्योंकि int से फ़्लोट में रूपांतरण छोटा नहीं है, अंतर से लंबे समय तक रूपांतरण के विपरीत। आप दोनों कंपाइलर को जटिल करने के लिए बहस कर रहे हैं (जिसे यह पता लगाना होगा कि इस अनुक्रम को सुरक्षित रूप से उपयोग किया जा सकता है) * और * जिटर (जिसे एक अनुक्रमित लोड का उत्पादन करने के लिए इस अनुक्रम को पहचानना है), या अन्यथा गलत या धीमा कोड उत्पन्न करना अब हमें जो मिला है उससे ज्यादा। और आईएल आकार को कम करने के लिए, जो अपेक्षाकृत महत्वहीन है - जब्त ऑब्जेक्ट कोड का आकार बहुत अधिक मायने रखता है, और इस मामले में कोई कमी नहीं होगी। –
(मैं अनिवार्य रूप से मौजूदा उत्तरों को पहले से कह रहा हूं, लेकिन संभवतः थोड़ा अधिक प्रत्यक्ष है।) –