c# - बाइट+बाइट=int... क्यों?




type-conversion (10)

इस सी # कोड को देख रहे हैं:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

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

byte z = (byte)(x + y); // this works

मैं क्या सोच रहा हूं क्यों? क्या यह वास्तुशिल्प है? दार्शनिक?

हमारे पास है:

  • int + int = int
  • long + long = long
  • float + float = float
  • double + double = double

तो क्यों नहीं:

  • byte + byte = byte
  • short + short = short ?

पृष्ठभूमि का एक बिट: मैं "छोटी संख्याओं" (यानी <8) पर गणनाओं की एक लंबी सूची कर रहा हूं और इंटरमीडिएट परिणामों को एक बड़ी सरणी में संग्रहीत कर रहा हूं। एक बाइट सरणी (एक int सरणी के बजाय) का उपयोग करना तेज है (कैश हिट के कारण)। लेकिन कोड के माध्यम से फैले व्यापक बाइट-कास्ट इसे अधिक अपठनीय बनाते हैं।


सी#

ईसीएमए -334 का कहना है कि जोड़ को केवल int + int, uint + uint, long + long और ulong + ulong (ECMA-334 14.7.4) पर कानूनी के रूप में परिभाषित किया गया है। ऐसे में, ये उम्मीदवार संचालन 14.4.2 के संबंध में विचार किए जाने हैं। चूंकि बाइट से int, uint, लंबे और उलझन में अंतर्निहित प्रभाव हैं, इसलिए सभी अतिरिक्त फ़ंक्शन सदस्य 14.4.2.1 के तहत लागू फ़ंक्शन सदस्य हैं। हमें 14.4.2.3 में नियमों द्वारा सर्वोत्तम निहित कास्ट मिलना है:

कास्टिंग (सी 1) से int (टी 1) कास्टिंग (सी 2) से यूआईटी (टी 2) या उलोंग (टी 2) से बेहतर है क्योंकि:

  • यदि टी 1 int है और टी 2 यूंट है, या उलझन में है, सी 1 बेहतर रूपांतरण है।

कास्टिंग (सी 1) से int (टी 1) कास्टिंग (सी 2) से लंबा (टी 2) से बेहतर है क्योंकि int से लंबे समय तक एक निहित कास्ट होता है:

  • यदि टी 1 से टी 2 में एक अंतर्निहित रूपांतरण मौजूद है, और टी 2 से टी 1 तक कोई अंतर्निहित रूपांतरण मौजूद नहीं है, तो सी 1 बेहतर रूपांतरण है।

इसलिए int + int फ़ंक्शन का उपयोग किया जाता है, जो एक int देता है।

यह कहने का एक बहुत लंबा रास्ता है कि इसे सी # विनिर्देश में बहुत गहरा दफनाया गया है।

CLI

सीएलआई केवल 6 प्रकार (int32, देशी int, int64, F, O, और &) पर काम करता है। (ईसीएमए -335 विभाजन 3 खंड 1.5)

बाइट (int8) उन प्रकारों में से एक नहीं है, और अतिरिक्त रूप से इसके अलावा एक int32 के लिए स्वचालित रूप से coerced है। (ईसीएमए -335 विभाजन 3 खंड 1.6)


"यह बिल्कुल क्यों होता है" के संदर्भ में ऐसा इसलिए होता है क्योंकि बीटी, एसबीईटी, शॉर्ट या यूहॉर्ट के साथ अंकगणित के लिए सी # द्वारा परिभाषित कोई ऑपरेटर नहीं हैं, जैसा कि अन्य ने कहा है। यह उत्तर इस ऑपरेटर को परिभाषित नहीं किया गया है।

मेरा मानना ​​है कि यह मूल रूप से प्रदर्शन के लिए है। प्रोसेसर के पास 32 बिट्स के साथ अंकगणित करने के लिए मूल संचालन होते हैं। परिणाम से वापस बाइट में रूपांतरण करना स्वचालित रूप से किया जा सकता है, लेकिन परिणामस्वरूप उस मामले में प्रदर्शन दंड का परिणाम होगा जहां आप वास्तव में उस व्यवहार को नहीं चाहते हैं।

मुझे लगता है कि एनोटेटेड सी # मानकों में से एक में इसका उल्लेख है। जा रहा है ...

संपादित करें: कष्टप्रद, मैंने अब एनोटेटेड ईसीएमए सी # 2 स्पेक, एनोटेटेड एमएस सी # 3 स्पेक और एनोटेशन सीएलआई स्पेक के माध्यम से देखा है, और इनमें से कोई भी इसका उल्लेख नहीं कर सकता है। मुझे यकीन है कि मैंने उपर्युक्त कारण देखा है, लेकिन अगर मुझे पता है तो मुझे उड़ा दिया गया है। माफी, संदर्भ प्रशंसकों :(


अन्य सभी महान टिप्पणियों के अलावा, मैंने सोचा कि मैं एक छोटी सी बोली जोड़ूंगा। बहुत सी टिप्पणियों ने सोचा है कि क्यों int, long, और बहुत अधिक संख्यात्मक कोई अन्य संख्या इस नियम का पालन नहीं करती है ... अंकगणित के जवाब में एक "बड़ा" प्रकार लौटाता है।

प्रदर्शन के साथ बहुत सारे उत्तरों को करना पड़ता है (ठीक है, 32 बिट 8 बिट से तेज है)। हकीकत में, एक 8 बिट नंबर 32 बिट सीपीयू के लिए अभी भी 32 बिट नंबर है .... भले ही आप दो बाइट्स जोड़ते हैं, सीपीयू पर चलने वाले डेटा का हिस्सा 32 बिट्स पर निर्भर करता है ... इसलिए इन्ट्स जोड़ना नहीं है दो बाइट जोड़ने से कोई भी "तेज" हो ... यह सब सीपीयू के समान ही है। अब, दो इंच जोड़ना 32 बिट प्रोसेसर पर दो लम्बाई जोड़ने से तेज होगा, क्योंकि दो लम्बाई जोड़ने के लिए अधिक माइक्रोप्स की आवश्यकता होती है क्योंकि आप प्रोसेसर शब्द से अधिक संख्याओं के साथ काम कर रहे हैं।

मुझे लगता है कि बाइट अंकगणित के कारण मूलभूत कारणों के कारण मूल स्पष्ट और सीधे आगे है: 8 बिट बस बहुत दूर नहीं जाते हैं! : डी 8 बिट्स के साथ, आपके पास 0-255 की एक हस्ताक्षरित रेंज है। यह काम करने के लिए बहुत सारे कमरे नहीं है ... अंकगणित में उनका उपयोग करते समय आप बाइट सीमाओं में भागने की संभावना को बहुत अधिक है। हालांकि, इनट्स, या लम्बे, या युगल इत्यादि के साथ काम करते समय आप बिट्स से बाहर निकलने का मौका काफी कम है ... इतना कम है कि हम शायद ही कभी अधिक आवश्यकता की आवश्यकता महसूस करते हैं।

बाइट से int तक स्वचालित रूपांतरण तार्किक है क्योंकि बाइट का स्तर इतना छोटा है। Int से लंबे, स्वचालित से दोहरी, आदि तक स्वचालित रूपांतरण तार्किक नहीं है क्योंकि उन संख्याओं में महत्वपूर्ण पैमाने है।


आपके कोड स्निपेट की तीसरी पंक्ति:

byte z = x + y;

वास्तव में मतलब है

byte z = (int) x + (int) y;

इसलिए, बाइट्स पर कोई + ऑपरेशन नहीं है, बाइट्स को पहले पूर्णांक में डाला जाता है और दो पूर्णांक के अतिरिक्त परिणाम एक (32-बिट) पूर्णांक होता है।


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


मुझे याद है कि जॉन स्कीट से कुछ पढ़ना (अब यह नहीं मिल रहा है, मैं देख रहा हूं) कैसे बाइट वास्तव में + ऑपरेटर को अधिभारित नहीं करता है। वास्तव में, जब आपके नमूने में दो बाइट जोड़ते हैं, तो प्रत्येक बाइट वास्तव में एक int में परिवर्तित हो रहा है। इसका नतीजा स्पष्ट रूप से एक int है। अब जब यह इस तरह से डिजाइन किया गया था, तो मैं जॉन स्कीट को पोस्ट करने के लिए इंतजार करूंगा :)

संपादित करें: इसे मिला! here इस विषय के बारे में महान जानकारी।


मेरा संदेह यह है कि सी # वास्तव में इंटेल पर परिभाषित operator+ कॉल कर रहा है (जो एक int देता है जब तक कि आप checked ब्लॉक में न हों), और इन दोनों को अपने bytes / shorts को ints कास्टिंग कर दें। यही कारण है कि व्यवहार असंगत प्रतीत होता है।


मैंने सोचा कि मैंने इसे कहीं पहले देखा था। इस लेख से, पुरानी नई बात :

मान लीजिए कि हम एक फंतासी दुनिया में रहते थे जहां 'बाइट' पर ऑपरेशन के परिणामस्वरूप 'बाइट' होता था।

byte b = 32;
byte c = 240;
int i = b + c; // what is i?

इस फंतासी दुनिया में, मेरा मूल्य 16 होगा! क्यूं कर? क्योंकि + ऑपरेटर के लिए दो ऑपरेशंस दोनों बाइट्स हैं, इसलिए योग "बी + सी" को बाइट के रूप में गणना की जाती है, जिसके परिणामस्वरूप 16 पूर्णांक ओवरफ़्लो के कारण होता है। (और, जैसा कि मैंने पहले उल्लेख किया था, पूर्ण सुरक्षा हमले वेक्टर पूर्णांक ओवरफ्लो है।)

संपादित करें : रेमंड बचाव कर रहा है, अनिवार्य रूप से, दृष्टिकोण सी और सी ++ मूल रूप से लिया गया। टिप्पणियों में, वह इस तथ्य का बचाव करता है कि सी # भाषा पिछड़ा संगतता के आधार पर एक ही दृष्टिकोण लेता है।


यह भाषा डिजाइनरों के हिस्से पर शायद एक व्यावहारिक निर्णय था। आखिरकार, एक इंट एक इंट 32 है, 32-बिट हस्ताक्षरित पूर्णांक। जब भी आप int से छोटे प्रकार के एक पूर्णांक ऑपरेशन करते हैं, तो इसे किसी भी 32 बिट CPU द्वारा किसी भी 32 बिट पर हस्ताक्षरित int में परिवर्तित किया जा रहा है। वह, छोटे पूर्णांक बहने की संभावना के साथ संयुक्त, शायद सौदा सील कर दिया। यह आपको लगातार / नीचे प्रवाह की जांच करने की गड़बड़ी से बचाता है, और जब बाइट्स पर एक अभिव्यक्ति का अंतिम परिणाम सीमा में होगा, इस तथ्य के बावजूद कि कुछ मध्यवर्ती चरण में यह सीमा से बाहर होगा, आपको सही मिल जाएगा परिणाम।

एक और विचार: इन प्रकारों पर ओवर / अंडर-फ्लो को अनुकरण करना होगा, क्योंकि यह सबसे संभावित लक्ष्य CPUs पर स्वाभाविक रूप से नहीं होगा। क्यों परेशान?


यह मेरे उत्तर के अधिकांश भाग के लिए है जो इस विषय से संबंधित है, पहले here एक समान प्रश्न पर सबमिट किया गया here

Int32 से छोटे अभिन्न संख्या वाले सभी संचालन डिफ़ॉल्ट रूप से गणना से पहले 32 बिट्स तक गोल होते हैं। परिणाम इंट 32 क्यों है इसे छोड़ने के लिए बस इसे छोड़ना है क्योंकि यह गणना के बाद है। यदि आप एमएसआईएल अंकगणितीय ऑपोड्स की जांच करते हैं, तो वे इंटी 32 और इंट 64 के साथ संचालित एकमात्र अभिन्न संख्यात्मक प्रकार हैं। यह "डिजाइन द्वारा" है।

यदि आप परिणाम को इंटेल 16 प्रारूप में वापस चाहते हैं, तो यदि आप कोड में कास्ट करते हैं तो यह अप्रासंगिक है, या कंपाइलर (hypotetically) "हुड के तहत" रूपांतरण को उत्सर्जित करता है।

उदाहरण के लिए, Int16 अंकगणित करने के लिए:

short a = 2, b = 3;

short c = (short) (a + b);

दो नंबर 32 बिट्स तक विस्तारित होंगे, जोड़े जाएंगे, फिर 16 बिट्स पर वापस छेड़छाड़ की जाएगी, इस प्रकार एमएस ने इसका इरादा किया है।

शॉर्ट (या बाइट) का उपयोग करने का लाभ प्राथमिक रूप से ऐसे मामलों में भंडारण होता है जहां आपके पास बड़ी मात्रा में डेटा (ग्राफ़िकल डेटा, स्ट्रीमिंग इत्यादि) होता है।







type-conversion