2016-02-25 2 views
11

मैं हाल ही में denormalized परिभाषा में आया था और मैं समझता हूं कि कुछ संख्याएं हैं जिन्हें सामान्यीकृत रूप में प्रदर्शित नहीं किया जा सकता है क्योंकि वे अपने संबंधित प्रकार में फिट होने के लिए बहुत छोटे हैं। आईईईईdenormalized संख्या सी #

enter image description here

तो मैं क्या करने की कोशिश कर रहा था पकड़ जब एक denormalized संख्या एक पैरामीटर इस संख्या के साथ गणना से बचने के लिए के रूप में पारित किया जा रहा है साथ अनुसार। अगर मैं सही समझ रहा हूँ मैं सिर्फ denormalized

private bool IsDenormalizedNumber(float number) 
{ 
    return Math.Pow(2, -149) <= number && number<= ((2-Math.Pow(2,-23))*Math.Pow(2, -127)) || 
      Math.Pow(-2, -149) <= number && number<= -((2 - Math.Pow(2, -23)) * Math.Pow(2, -127)); 
} 

मेरी व्याख्या सही है की सीमा के भीतर नंबरों के लिए देखने की जरूरत है?

+1

इसे देखने का सही तरीका लगता है। हालांकि, आपके सूत्र परिभाषा से मेल नहीं खाते हैं: 'वापसी Math.Pow (2, -149) <= संख्या और संख्या <= ((1-Math.Pow (2, -23)) * Math.Pow (2, - 126)) || Math.Pow (-2, -149)> = संख्या और संख्या> = - ((1 - Math.Pow (2, -23)) * Math.Pow (2, -126)) ' – Rob

+0

यह मेरे लिए गलत लगता है कि आप तुलना करने के लिए 'डबल' गणना और '<=' ऑपरेटर का उपयोग कर रहे हैं। मुझे लगता है कि मछली पकड़ने के कार्निवल की तुलना में अधिक कास्टिंग चल रहा है और इससे इनमें से कोई भी तुलना खत्म हो सकती है। – Enigmativity

+0

तो, क्या आपको लगता है कि मुझे डबल और फ्लोट के साथ मिल रहे विभिन्न प्रारूपों के कारण गलत तुलना मिल रही है? – Nandhi

उत्तर

4

मुझे लगता है कि बिट्स का निरीक्षण करने के लिए एक बेहतर दृष्टिकोण होगा। सामान्यीकृत या denormalized बाइनरी प्रतिनिधित्व की विशेषता है, मूल्य के नहीं। इसलिए, आप इसे इस तरह से अधिक विश्वसनीय रूप से पहचानने में सक्षम होंगे और आप बिना किसी संभावित और संभावित रूप से खतरनाक फ़्लोटिंग पॉइंट तुलना कर सकते हैं।

मैंने आपके लिए कुछ रननेबल कोड रखा है, ताकि आप इसे काम देख सकें। मैंने इस कोड को युगल के बारे में एक समान प्रश्न से अनुकूलित किया। Denormal का पता लगाने एक्सपोनेंट और महत्व को पूरी तरह से उत्साहित करने से कहीं अधिक सरल है, इसलिए मैं कोड को सरल बनाने में सक्षम था।

यह क्यों काम करता है ... एक्सपोनेंट ऑफसेट नोटेशन में संग्रहीत किया जाता है। एक्सपोनेंट के 8 बिट्स मान 1 से 254 (0 और 255 विशेष मामलों के लिए आरक्षित हैं) ले सकते हैं, फिर उन्हें -127 द्वारा समायोजित ऑफसेट किया जाता है -126 (1-127) से 127 (254-127) की सामान्यीकृत रेंज)। एक्सपोनेंट को असामान्य मामले में 0 पर सेट किया गया है। मुझे लगता है कि यह केवल इसलिए आवश्यक है क्योंकि .NET महत्व पर अग्रणी बिट को स्टोर नहीं करता है। आईईईई 754 के अनुसार, इसे किसी भी तरह से संग्रहीत किया जा सकता है। ऐसा प्रतीत होता है कि सी # ने इसे साइन बिट के पक्ष में छोड़ने का विकल्प चुना है, हालांकि मेरे पास उस अवलोकन को वापस करने के लिए कोई ठोस विवरण नहीं है।

किसी भी मामले में, वास्तविक कोड काफी सरल है। जो कुछ आवश्यक है वह एक्सपोनेंट और 0 के लिए परीक्षण 8 बिट्स को उत्पादित करना है। 0 के आसपास एक विशेष मामला है, जिसे नीचे संभाला जाता है।

नोट: टिप्पणी चर्चा के अनुसार, यह कोड मंच विशिष्ट कार्यान्वयन विवरण (x86_64 इस परीक्षण मामले में) पर निर्भर करता है। जैसा कि @ चेन्यून सुगिहारा ने बताया, सीएलआई इस व्यवहार को सुनिश्चित नहीं करता है और यह एआरएम जैसे अन्य प्लेटफार्मों पर भिन्न हो सकता है।

using System; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("-120, denormal? " + IsDenormal((float)Math.Pow(2, -120))); 
      Console.WriteLine("-126, denormal? " + IsDenormal((float)Math.Pow(2, -126))); 
      Console.WriteLine("-127, denormal? " + IsDenormal((float)Math.Pow(2, -127))); 
      Console.WriteLine("-149, denormal? " + IsDenormal((float)Math.Pow(2, -149))); 
      Console.ReadKey(); 
     } 

     public static bool IsDenormal(float f) 
     { 
      // when 0, the exponent will also be 0 and will break 
      // the rest of this algorithm, so we should check for 
      // this first 
      if (f == 0f) 
      { 
       return false; 
      } 
      // Get the bits 
      byte[] buffer = BitConverter.GetBytes(f); 
      int bits = BitConverter.ToInt32(buffer, 0); 
      // extract the exponent, 8 bits in the upper registers, 
      // above the 23 bit significand 
      int exponent = (bits >> 23) & 0xff; 
      // check and see if anything is there! 
      return exponent == 0; 
     } 
    } 
} 

उत्पादन होता है:

-120, denormal? False 
-126, denormal? False 
-127, denormal? True 
-149, denormal? True 

सूत्रों का कहना है:
extracting mantissa and exponent from double in c#
https://en.wikipedia.org/wiki/IEEE_floating_point
https://en.wikipedia.org/wiki/Denormal_number
http://csharpindepth.com/Articles/General/FloatingPoint.aspx

कोड से अनुकूलित:
+०१२३५१६४१०६extracting mantissa and exponent from double in c#

+1

मुझे लगता है कि आपका उत्तर कार्यान्वयन विशिष्ट है। विवरण के लिए मेरे उत्तर में अद्यतन देखें। –

+0

वास्तव में यह @Cuneuneugihara है। मैंने पोर्टेबिलिटी पर विचार नहीं किया। इसे कॉल करने के लिए धन्यवाद। –

+1

कोई समस्या नहीं, मुझे लगता है कि आपको पीएचडी की आवश्यकता है। इन पागल चीजों में उन सभी चीजों को समझने के लिए जो उनके साथ चल रहे हैं। मैं संख्यात्मक गणनाओं के इन जटिल यूनिकॉर्न का पता लगाने के लिए उपयोग के मामले के बारे में बहुत उत्सुक हूं। ऐसा लगता है कि वे बहुत जटिलता जोड़ रहे हैं और मैं सोच रहा हूं कि किसी भी समस्या का सरल जवाब होना चाहिए कि वे हल करने की कोशिश कर रहे हैं। सभी ने कहा कि अगर उन्हें वास्तव में उन्हें पहचानने की ज़रूरत है तो मुझे लगता है कि आपका समाधान प्रभावी है जब तक पोर्टेबिलिटी खेल में नहीं आती है। –

2

मेरी समझ से denormalized संख्या कुछ मामलों में अंडरफ्लो के साथ मदद के लिए हैं (Denormalized Numbers - IEEE 754 Floating Point का उत्तर देखें)।

तो एक असामान्य संख्या प्राप्त करने के लिए आपको इसे स्पष्ट रूप से बनाना होगा या अन्यथा एक अंडरफ्लो का कारण बनना होगा। पहले मामले में ऐसा लगता है कि एक शाब्दिक denormalized संख्या कोड में निर्दिष्ट किया जाएगा, और यहां तक ​​कि अगर किसी ने कोशिश की तो मुझे यकीन नहीं है कि .NET इसे अनुमति देगा। दूसरे मामले में जब तक आप checked संदर्भ में हैं, आपको OverflowException अंकगणितीय गणना में किसी भी अतिप्रवाह या अंडरफ़्लो के लिए फेंक दिया जाना चाहिए ताकि यह एक असामान्य संख्या प्राप्त करने की संभावना के खिलाफ सुरक्षा करे। unchecked संदर्भ में मुझे यकीन नहीं है कि एक अंडरफ्लो आपको एक असामान्य संख्या में ले जाएगा, लेकिन आप इसे आजमा सकते हैं और देख सकते हैं कि आप unchecked में गणना चलाने के इच्छुक हैं या नहीं।

लंबी कहानी छोटी है यदि आप checked में चल रहे हैं तो आप इसके बारे में चिंता नहीं कर सकते हैं और यदि आप उस संदर्भ में भागना चाहते हैं तो unchecked में एक अंडरफ़्लो देखें और देखें।

संपादित

मैं अपने जवाब को अद्यतन करने के बाद से एक टिप्पणी पर्याप्त पर्याप्त महसूस नहीं किया था चाहता था। सबसे पहले मैंने checked संदर्भ के बारे में टिप्पणी की, जो केवल गैर-फ़्लोटिंग पॉइंट गणनाओं (जैसे int) पर लागू होती है और float या double पर लागू होती है। उस पर मेरी गलती थी।

denormalized संख्या के साथ मुद्दा यह है कि वे सीएलआई में संगत नहीं हैं। ध्यान दें कि मैं "सीएलआई" का उपयोग कैसे कर रहा हूं, न कि "सी #" क्योंकि हमें इस मुद्दे को समझने के लिए केवल सी # से कम स्तर पर जाना होगा। सामान्य भाषा इन्फ्रास्ट्रक्चर एनोटेट स्टैंडर्ड विभाजन मैं धारा 12.1.3 दूसरा नोट (पुस्तक के पृष्ठ 125) से यह कहता है:

यह मानक denormalized चल बिन्दु संख्या पर अंकगणितीय आपरेशनों के व्यवहार को निर्दिष्ट नहीं करता, और न ही यह निर्दिष्ट करता है कि इस तरह के प्रतिनिधित्व कब बनाए जाएंगे या नहीं। यह आईईसी 605 9 5: 1 9 8 9 को ध्यान में रखते हुए है। इसके अलावा, यह मानक निर्दिष्ट नहीं करता है कि बनाए गए NaNs के सटीक बिट पैटर्न को कैसे एक्सेस किया जाए, न ही व्यवहार को 32-बिट और 64-बिट प्रतिनिधित्व के बीच NaN को परिवर्तित करते समय। इस व्यवहार का जानबूझकर कार्यान्वयन विशिष्ट छोड़ दिया गया है।

तो सीएलआई स्तर पर denormalized संख्याओं के हैंडलिंग जानबूझकर कार्यान्वयन के लिए छोड़ दिया गया है।इसके अलावा, यदि आप float.Epsilon (here मिला) के लिए प्रलेखन को देखते हैं, जो एक फ्लोट द्वारा प्रस्तुत किया जाने वाला सबसे छोटा सकारात्मक संख्या है, तो आपको अधिकांश मशीनों पर एक असामान्य संख्या मिल जाएगी जो दस्तावेज़ीकरण में सूचीबद्ध है (जो लगभग 1.4e-45 है)। यह है कि @ केविन बर्डेट अपने जवाब में सबसे ज्यादा देख रहे थे। कहा जाता है कि यदि आप पृष्ठ पर आगे नीचे स्क्रॉल आप "प्लेटफ़ॉर्म नोट्स"

एआरएम सिस्टम पर, एप्सिलॉन निरंतर का मूल्य बहुत छोटा है के अंतर्गत निम्नलिखित उद्धरण देखेंगे पता लगाया जा तो यह शून्य के बराबर है । आप एक वैकल्पिक ईपीएसलॉन मान को परिभाषित कर सकते हैं जो इसके बजाय 1.175494351 ई -38 के बराबर है।

तो वहाँ पोर्टेबिलिटी के मुद्दों है कि भूमिका निभाते हैं कर सकते हैं जब आप मैन्युअल रूप से भी सिर्फ .NET CLR के लिए denormalized संख्या से निपटने (जो CLI के एक कार्यान्वयन है) के साथ काम कर रहे हैं। असल में यह एआरएम विशिष्ट मूल्य एक प्रकार का दिलचस्प है क्योंकि यह सामान्यीकृत संख्या प्रतीत होता है (मैंने IsDenormal(1.175494351E-38f) के साथ @ केविन बर्डेट से फ़ंक्शन का उपयोग किया और यह गलत हो गया)। सीएलआई में उचित चिंताएं अधिक गंभीर हैं क्योंकि सीएलआई मानक पर एनोटेशन के अनुसार डिजाइन द्वारा उनके हैंडलिंग पर कोई मानकीकरण नहीं है। तो यह उदाहरण के लिए मोनो या एक्समारिन पर एक ही कोड के साथ क्या होगा, इसके बारे में सवाल छोड़ देता है जो .NET CLR की तुलना में सीएलआई का एक अंतर कार्यान्वयन है।

अंत में मैं अपनी पिछली सलाह पर वापस आ गया हूं। बस denormalized संख्याओं के बारे में चिंता मत करो, वे चुपचाप आपकी मदद करने के लिए हैं और यह कल्पना करना मुश्किल है कि आपको उन्हें विशेष रूप से बाहर करने की आवश्यकता क्यों होगी। इसके अलावा @ हंसपैसेंट ने आपको बताया है कि वैसे भी आपको भी मुकाबला नहीं होगा। कल्पना करना मुश्किल है कि आप double में सबसे छोटे, सकारात्मक सामान्यीकृत संख्या के तहत कैसे जा रहे हैं जो बेहद कम है।

+0

मुझे नहीं लगता कि यह सटीक @ChiuneSugihara है। मैं दोनों अक्षर और संचालन (डबल से विशेष रूप से कास्ट) का उपयोग करके denormalized फ्लोट बनाने में सक्षम था। मैंने एक अनचेक संदर्भ दर्ज किए बिना ऐसा किया। –

+0

आप हमेशा चेक या अनचेक होते हैं चाहे आप कुछ निर्दिष्ट करते हैं या नहीं। चेक किए गए सिर्फ इसका मतलब है कि आईएल कोड उत्सर्जित किए जाएंगे जो ओवरफ्लो की जांच भी करेंगे जबकि अनचेक का मतलब है कि आईएल कोड उत्सर्जित किए जाएंगे। \ चेक किए गए कंपाइलर स्विच की उपस्थिति या अनुपस्थिति के माध्यम से निर्माण सेट के लिए एक वैश्विक सेटिंग है। जहां तक ​​denormalized फ्लोट्स, मैंने देखा कि आप उन्हें बनाने में सक्षम थे। मैंने यह नहीं कहा कि आप केवल इतना नहीं कर सकते थे कि मुझे यकीन नहीं था और सोचा था कि आप शायद कुछ मामलों में स्पष्ट रूप से नहीं कर सकते थे। हालांकि यह कार्यान्वयन विशिष्ट है। –

+0

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

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