हम सभी ने स्कूल में फ़्लोटिंग पॉइंट नंबरों के बारे में सीखा है। उन पूर्णांकों के विपरीत जिनका कोई दशमलव बिंदु नहीं है।
किसी को यह जानने के लिए गणित विशेषज्ञ होने की आवश्यकता नहीं है कि संख्या पाँच एक पूर्णांक है जबकि 5.43 एक फ्लोटिंग पॉइंट संख्या है। स्पष्ट रूप से, हम सभी दशमलव बिंदु से परिचित हैं जो कि दोनों के बीच अंतर का एक स्पष्ट बिंदु है।
बेशक, यह कोई आश्चर्य की बात नहीं है कि फ़्लोट्स का उपयोग प्रोग्रामिंग भाषाओं में किया जाता है और यहां तक कि एक विशिष्ट आदिम डेटा प्रकार के रूप में वर्गीकृत किया जाता है क्योंकि यह दैनिक गणना के लिए कितना आवश्यक है।
जब आप पायथन या जावा सीखना शुरू करते हैं, तो आप फ्लोट डेटा प्रकार का उपयोग करेंगे। विशेष रूप से, जब आप दो फ्लोटिंग पॉइंट नंबरों के बीच डिवीजन ऑपरेशन करते हैं।
पायथन में, भले ही आपको फ्लोटिंग पॉइंट नंबर घोषित करने की आवश्यकता न हो, इनमें से दो नंबरों को विभाजित करने से समान डेटा प्रकार की संख्या हो सकती है, जैसा कि नीचे दिखाया गया है:
हम जावा में भी वही परिणाम उत्पन्न कर सकते हैं, भले ही हमें उपयोग किए गए सभी चरों के लिए 'फ्लोट' आदिम डेटा प्रकार को स्पष्ट रूप से घोषित करना पड़े।
जैसा कि कोई बता सकता है, इस तरह की संगणना कई अनुप्रयोगों के लिए आवश्यक है, और यही कारण है कि इन दोनों प्रोग्रामिंग भाषाओं में फ्लोटिंग पॉइंट नंबरों के साथ संचालन एक सुविधा के रूप में उपलब्ध है।
काफी अलग तरीके से, यदि आप सॉलिडिटी सीख रहे हैं, तो आपने देखा होगा कि इसमें फ्लोटिंग पॉइंट नंबर डेटा टाइप शामिल नहीं है।
इसके बजाय, यदि आपने सॉलिडिटी में कोई कोड लिखा है, तो आप या तो हस्ताक्षरित या अहस्ताक्षरित पूर्णांक प्रकार की संख्याओं का उपयोग करेंगे।
इसलिए, यदि आप समान संगणना करना चाहते हैं - पांच विभाजित दो - जैसा कि पिछले अनुभाग में दिखाया गया है, स्मार्ट अनुबंध के हिस्से के रूप में यह कैसा दिखेगा:
हालाँकि, आप जो परिणाम प्राप्त करेंगे, वह समान नहीं होगा, क्योंकि सॉलिडिटी फ्लोट डेटा प्रकार का समर्थन नहीं करती है। कम से कम, अभी तो नहीं।
विशेष रूप से, सॉलिडिटी परिणाम को शून्य की ओर ले जाएगी। कौन सा, इस मामले में, और जैसा कि ऊपर दिखाया गया है, परिणाम दो का मान होगा। इसे दोनों नंबरों पर मॉडुलो ऑपरेशन के रूप में सोचें।
जबकि सामान्य परिस्थितियों में, यह ज्यादा मायने नहीं रखता है, ऐसे समय होते हैं जब परिणाम गणना में त्रुटि का कारण बन सकता है। यही कारण है कि जितना संभव हो विभाजन संचालन से बचने या स्थगित करने की सिफारिश की जाती है।
यहां तक कि अगर स्कूल में BODMAS नियम के अनुसार सभी गणित के छात्रों को गुणा से पहले भाग की गणना करने की आवश्यकता होती है, अगर आपको सॉलिडिटी में पूर्णांक विभाजन करना है तो इसकी अनुशंसा नहीं की जाती है।
आइए जानें कि क्यों, इस सरल उदाहरण से, जो तीन संख्याओं के साथ गुणा और भाग करता है:
यदि आप स्मार्ट अनुबंध की तैनाती करते समय संख्या एक, तीन और पांच दर्ज करते हैं, तो आपको getResult और getResult2 कार्यों के लिए समान मूल्य प्राप्त करना चाहिए, है ना?
यदि आप एक साधारण कैलकुलेटर का उपयोग करते हैं, तो आपको 1.666 का फ्लोट मान प्राप्त करना चाहिए, जो फ्लोट वैल्यू की अनुपस्थिति के कारण सॉलिडिटी में एक में बदल जाता है।
दुर्भाग्य से, ऐसा नहीं होता है, जब आप getResult और getResult2 फ़ंक्शंस के परिणामों की जाँच करते हैं, जैसा कि नीचे दिखाया गया है:
यदि हम पहले विभाजन करते हैं, तो हमें शून्य का अंतिम परिणाम मिलता है। एक के अपेक्षित मूल्य के विपरीत, जब आप उस ऑपरेशन को getResult फ़ंक्शन में अंत तक स्थगित कर देते हैं।
जैसा कि आप बता सकते हैं, भले ही हमने फ्लोट मानों की अनुपस्थिति का अनुमान लगाकर इस मान की गणना की हो, फिर भी एक त्रुटि है जो फसल पैदा करती है जो सटीकता में हानि का कारण बन सकती है। जो, बदले में, आर्थिक नुकसान का अनुवाद कर सकता है जिसे आसानी से बायपास किया जा सकता है।
तो, हम पूर्णांक विभाजन त्रुटि को कैसे रोक सकते हैं? इससे भी महत्वपूर्ण बात यह है कि हम अपनी संगणना के लिए सटीकता कैसे बढ़ा सकते हैं? आइए ऐसा करने के तीन सबसे सामान्य तरीकों के बारे में जानें।
यह देखते हुए कि इस त्रुटि को दरकिनार करने के लिए कई दृष्टिकोण हैं, आइए सबसे सरल सुधार से शुरू करें, और इसे एक दिन बुलाने से पहले कुछ और देखें।
विधि # 1: एक गुणक का प्रयोग करें
अब, विभाजन संक्रिया को अंत में रखने के साथ, यह सुनिश्चित करने का एक तरीका है कि आप त्रुटियों या गलत मानों के साथ समाप्त न हों, एक गुणक का उपयोग करना है। नीचे दिए गए उदाहरण में, हम पहले इस्तेमाल की गई समान तीन संख्याओं के साथ 100 के गुणक का उपयोग करेंगे।
अब, जब आप निम्नलिखित कोड के साथ अनुबंध को तैनात करते हैं और दोनों कार्यों को कॉल करते हैं, तो यह आउटपुट होता है:
चूंकि वांछित आउटपुट 1.666 या 166/100 है, हम देख सकते हैं कि getResult2 मान हमें आवश्यक सटीकता प्रदान करता है जब गुणक तीन संख्याओं के संयोजन के साथ काम करता है। बेशक, यदि आप गुणक का उपयोग नहीं करते हैं जैसा कि getResult फ़ंक्शन में है, तो आपको 1 प्राप्त होगा।
जहां 0.666 को परिणाम से छोटा कर दिया जाता है, जब आप सॉलिडिटी का उपयोग करते हैं तो डिफ़ॉल्ट रूप से अपेक्षित होता है। इसलिए, इस मान को पुनः प्राप्त करने के लिए, आपको केवल परिणाम को गुणक से विभाजित करना है।
जैसा कि आप जानते हैं, जब हस्ताक्षरित और अहस्ताक्षरित दोनों पूर्णांकों के मामले में राउंड ऑफ करने की बात आती है, तो सॉलिडिटी शून्य की ओर बढ़ जाती है, इसलिए यह फिक्स हस्ताक्षरित पूर्णांकों के मामले में भी काम करता है, एक बार जब आप नीचे दिए गए कोड को माइनस एक के साथ तैनात और चलाते हैं , तीन और पांच:
जब हस्ताक्षर किए गए पूर्णांकों के लिए फ़ंक्शन द्वारा जनरेट किए गए मानों की बात आती है, तो वे यहां हैं:
स्पष्ट रूप से, हम गुणक का उपयोग करके हस्ताक्षरित पूर्णांकों के लिए भी सटीकता बनाए रखने में सक्षम हैं। हालाँकि, हस्ताक्षरित पूर्णांकों को राउंड ऑफ करने का एक सटीक तरीका है जिसे हम आगे देखेंगे।
विधि #2: हस्ताक्षरित पूर्णांकों के लिए तल विभाजन का उपयोग करें
अब, यदि कोई नीचे दी गई संख्या रेखा को देखता है, तो दो अहस्ताक्षरित पूर्णांकों के बीच पूर्णांक विभाजन करने का परिणाम शून्य के करीब होता है। जैसा कि 1.666 प्राप्त करने के मामले में, सॉलिडिटी इसे 1 से बंद कर देती है, जो कि एक छोटी संख्या है।
हालाँकि, जब हस्ताक्षरित पूर्णांकों की बात आती है, तो -1.6666 के परिणाम को -1 तक गोल कर दिया जाएगा, जो कि दो संख्याओं में से बड़ा है। इसलिए, राउंडेड-टू-जीरो डिवीजन के विपरीत फ्लोर डिवीजन को यहां लागू किया जाना चाहिए जो कि डिफ़ॉल्ट रूप से सॉलिडिटी में लागू होता है। सटीकता के लिए, बिल्कुल।
यदि फ्लोट डेटा प्रकार उपलब्ध था, तो -1.666 के मान की गणना की जाएगी। जबकि सॉलिडिटी इसे नीचे -1 तक ले जाएगी, फ्लोर डिवीजन को हस्ताक्षरित पूर्णांकों पर लागू करने से यह -2 तक कम हो जाएगा।
जब आप getResult और getResult2 फ़ंक्शंस को कॉल करते हैं, तो हम मान प्राप्त करते हैं जैसा कि तर्कों के लिए नीचे दिखाया गया है माइनस एक, तीन और पांच:
जैसा कि आप बता सकते हैं, getResult गोल-प्रति-शून्य दृष्टिकोण का उपयोग करके मान की गणना करता है, जबकि getResult2 इसे फ्लोर डिवीजन के आधार पर सबसे छोटे पूर्णांक तक गोल करता है।
विधि #3: ABDKMath64x64 लाइब्रेरी का उपयोग करें
अब, अंतिम विधि के लिए, हम ABDKMath64x64 लाइब्रेरी का उपयोग करेंगे, जो विभाजन संचालन के परिणाम को निश्चित बिंदु संख्याओं में परिवर्तित करती है।
फिर भी, इस पुस्तकालय का उपयोग सटीकता में सुधार करने के लिए कहा जाता है, जो कि सॉलिडिटी में डिफ़ॉल्ट रूप से उपलब्ध शून्य विधि की ओर बढ़ने के विपरीत है। आउटपुट को समझने के लिए, आइए ऐड के परिणामों की तुलना div फंक्शन से करें, जैसा कि नीचे दिखाया गया है:
जब आप स्मार्ट अनुबंध की तैनाती करते समय तर्क 1, 1 और 1 जोड़ते हैं, तो आप मान प्राप्त करते हैं, जैसा कि नीचे दिखाया गया है:
इसमें कोई आश्चर्य नहीं होना चाहिए कि ऐड फ़ंक्शन दो का एक पूर्णांक मान लौटाता है, जिसमें तीन तर्कों को जोड़ा जाता है। Div फ़ंक्शन के लिए, एक int 128 मान लौटाया जाता है जो एक हस्ताक्षरित 64.64-बिट निश्चित बिंदु संख्या का प्रतिनिधित्व करता है और जिसके साथ आप सामान्य संख्या संचालन कर सकते हैं।
बेशक, ABDKMath64x64 पुस्तकालय एकमात्र ऐसा नहीं है जिसका उपयोग पूर्णांक विभाजन त्रुटि को रोकने के अलावा सटीकता में सुधार के लिए किया जा सकता है।
फ़िक्सिडिटी , DSMath और BANKEX लाइब्रेरी जैसे कुछ अन्य उदाहरण हैं जो विभिन्न संख्या स्वरूपों का उपयोग करते हैं। संख्या स्वरूप जो उपरोक्त उदाहरण में उपयोग किए गए 64.64-बिट निश्चित बिंदु संख्या प्रारूप से भिन्न हैं। इसलिए, जबकि ये पुस्तकालय खोज के लिए उपयोगी लग सकते हैं, कृपया याद रखें कि उनके संख्या प्रारूप उपलब्ध अन्य पुस्तकालयों में से किसी के साथ काम नहीं करेंगे।