2009-08-07 36 views
19

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

कठिनाई यह है कि आईईईई प्रारूप पूरी तरह से समान नहीं है। यदि कोई निम्न-स्तर कोड का उपयोग करना था और वास्तव में कम से कम महत्वपूर्ण बिट में एक जोड़ना था, तो परिणामी प्रारूप अगले उपलब्ध डबल नहीं हो सकता है। उदाहरण के लिए, यह एक विशेष केस नंबर हो सकता है जैसे पॉजिटिव इंफिनिटी या नाएन। उप-सामान्य मान भी हैं, जिन्हें मैं समझने का दावा नहीं करता हूं, लेकिन ऐसा लगता है कि "सामान्य" पैटर्न से विशिष्ट बिट पैटर्न अलग-अलग होते हैं।

एक "ईपीएसलॉन" मान उपलब्ध है, लेकिन मैंने इसकी परिभाषा कभी नहीं समझा है। चूंकि डबल मान समान रूप से दूरी पर नहीं हैं, इसलिए अगले उच्च मूल्य में परिणामस्वरूप डबल में कोई एकल मूल्य जोड़ा जा सकता है।

मुझे वास्तव में समझ में नहीं आता कि आईईईई ने अगले उच्च या निम्न मूल्य प्राप्त करने के लिए कोई फ़ंक्शन निर्दिष्ट क्यों नहीं किया है। मैं अकेला नहीं हो सकता जिसकी जरूरत है।

क्या अगला मूल्य प्राप्त करने का कोई तरीका है (बिना किसी लूप के छोटे और छोटे मान जोड़ने की कोशिश करता है)।

+2

आईईईई -754 * ने संशोधित (2008) मानक की धारा 5.3.1 में आवश्यकतानुसार 'अगली अप' और' अगली डाउन 'निर्दिष्ट की है, और मूल (1985) द्वारा अनुशंसित पहले के अगले' फ़ंक्शन ' मानक, और सी 99 में आवश्यक है। –

उत्तर

1

मुझे यकीन नहीं है कि मैं आपकी समस्या का पालन कर रहा हूं। निश्चित रूप से आईईईई मानक पूरी तरह से वर्दी है? उदाहरण के लिए, डबल परिशुद्धता संख्याओं के लिए wikipedia article से इस अंश को देखें।

3ff0 0000 0000 0000 = 1 
3ff0 0000 0000 0001 = 1.0000000000000002, the next higher number > 1 
3ff0 0000 0000 0002 = 1.0000000000000004 

बाइनरी या हेक्स प्रतिनिधित्व में केवल कम से कम महत्वपूर्ण बिट को बढ़ाने के साथ क्या गलत है?

जहां तक ​​विशेष संख्याएं (अनंत, NaN, आदि) जाती हैं, वे अच्छी तरह परिभाषित हैं, और उनमें से बहुत से नहीं हैं। सीमाएं समान रूप से परिभाषित की जाती हैं।

चूंकि आपने स्पष्ट रूप से इसमें देखा है, मुझे उम्मीद है कि मुझे छड़ी का गलत अंत मिल गया है। यदि यह आपकी समस्या के लिए पर्याप्त नहीं है, तो क्या आप कोशिश कर सकते हैं और स्पष्ट कर सकते हैं कि आप क्या हासिल करना चाहते हैं? आपका उद्देश्य यहाँ क्या है?

+0

क्या वह उन मामलों में काम करेगा जहां एक्सपोनेंट को बढ़ाना होगा? –

+0

मेरा लक्ष्य यह स्पष्ट रूप से करना है, अधिमानतः सी # से, लेकिन अगर मुझे करना है तो मैं थोड़ा स्तर तक पहुंच जाऊंगा। समस्या यह है कि आईईईई मानक सार्वजनिक डोमेन में नहीं है, और मैं इसे खरीदने का जोखिम नहीं उठा सकता। मानक आपके द्वारा दिखाए गए मामले के लिए बिट पैटर्न को परिभाषित करता है, लेकिन सभी असामान्य संख्याओं (जैसे उप-मानदंड) के लिए भी। इस कार्य को करने के लिए किसी को सभी संख्या प्रारूपों का पूरा विवरण नहीं पता होना चाहिए। लेकिन अगर आप खुद को बिट्स फ्लिप करते हैं, तो आपको करना होगा। क्या होगा यदि 'अगली' संख्या एक असामान्य है? जब तक आप सभी नियमों को नहीं जानते, आप वहां नहीं जा सकते! –

+1

@ मार्क टी: ठीक है, अब मैं आपकी समस्या को समझता हूं। मुझे एहसास नहीं हुआ कि मानक स्वतंत्र रूप से उपलब्ध नहीं था (अद्भुत)! यहां dnxtaft.f सहित कई फ़ंक्शंस के कार्यान्वयन हैं, जो x की दिशा में अगला फ़्लोटिंग पॉइंट मान देता है। शायद यह मदद करेगा? http://www.math.utah.edu/~beebe/software/ieee/ –

12

बिल्कुल ऐसा करने के लिए उपलब्ध फ़ंक्शंस हैं, लेकिन वे इस भाषा पर निर्भर कर सकते हैं कि आप किस भाषा का उपयोग करते हैं। दो उदाहरण:

  • आप एक सभ्य C99 गणित पुस्तकालय के लिए उपयोग किया है, तो आप nextafter (और इसके नाव और लंबी डबल वेरिएंट, nextafterf और nextafterl) का उपयोग कर सकते हैं; या nexttoward परिवार (जो दूसरे तर्क के रूप में एक लंबा डबल लेता है)।

  • अगर आप फोरट्रान लिखते हैं, आपके पास nearest आंतरिक उपलब्ध

अगर आप अपनी भाषा से सीधे इन उपयोग नहीं कर सकते हैं, तो आप उन्हें भी उस स्वतंत्र रूप से उपलब्ध में लागू कर रहे हैं देख सकते हैं, इस तरह के this one के रूप में।

2

हाँ, एक तरीका है। सी # में:

 public static double getInc (double d) 
     { 
       // Check for special values 
       if (double.IsPositiveInfinity(d) || double.IsNegativeInfinity(d)) 
        return d; 
       if (double.IsNaN(d)) 
        return d; 

       // Translate the double into binary representation 
       ulong bits = (ulong)BitConverter.DoubleToInt64Bits(d); 
       // Mask out the mantissa bits 
       bits &= 0xfff0000000000000L; 
       // Reduce exponent by 52 bits, so subtract 52 from the mantissa. 
       // First check if number is great enough. 
       ulong testWithoutSign = bits & 0x7ff0000000000000L; 
       if (testWithoutSign > 0x0350000000000000L) 
        bits -= 0x0350000000000000L; 
       else 
        bits = 0x0000000000000001L; 
       return BitConverter.Int64BitsToDouble((long)bits); 
} 

वृद्धि जोड़ा गया है और घटाया जा सकता है।

+0

यह नहीं करता है ' टी संकलित करें, और मुझे नहीं लगता कि आप ठीक से 'BitConverter.DoubleToInt64Bits' विधि का उपयोग कर रहे हैं। यदि आप किसी संख्या के बाइट प्रस्तुति को प्राप्त करना चाहते हैं, तो आपको 'बिटकॉन्टर.गेटबाइट्स' का उपयोग करना चाहिए (लेकिन फिर आपको यह सुनिश्चित करने की आवश्यकता है कि यदि आवश्यक हो तो आप एक्सपोनेंट को बढ़ाएं या घटाएं)। –

+0

यह संकलित नहीं करता है क्योंकि सी # उलंग/लंबे स्थिरांक और चर (जो बिट ऑपरेटरों के लिए बेवकूफ है) मिश्रण करने की अनुमति नहीं देता है। और आपने गलत सोचा, बिटकॉन्टर विधि वास्तव में आईईईई प्रारूप में डबल की आंतरिक बाइट संरचना वापस कर देती है। –

5

Thorsten एस कहते हैं, इस BitConverter वर्ग के साथ किया जा सकता है, लेकिन उसकी विधि मानता है कि DoubleToInt64Bits विधि रिटर्न double के आंतरिक बाइट संरचना है, जो ऐसा नहीं है। उस विधि द्वारा लौटाया गया पूर्णांक वास्तव में 0 और आपके बीच के प्रतिनिधित्व योग्य युगल की संख्या देता है। अर्थात। सबसे छोटा सकारात्मक डबल 1 द्वारा दर्शाया जाता है, अगला सबसे बड़ा डबल 2 इत्यादि आदि होता है। नकारात्मक संख्या long.MinValue से शुरू होती है और 0 डी से दूर जाती है।

तो तुम कुछ इस तरह कर सकते हैं:

public static double NextDouble(double value) { 

    // Get the long representation of value: 
    var longRep = BitConverter.DoubleToInt64Bits(value); 

    long nextLong; 
    if (longRep >= 0) // number is positive, so increment to go "up" 
     nextLong = longRep + 1L; 
    else if (longRep == long.MinValue) // number is -0 
     nextLong = 1L; 
    else // number is negative, so decrement to go "up" 
     nextLong = longRep - 1L; 

    return BitConverter.Int64BitsToDouble(nextLong); 
} 

यह Infinity और NaN, के साथ सौदा नहीं है, लेकिन आप उन लोगों के लिए जाँच करें और उनसे निपटने के जैसे आप चाहें, अगर आप इसके बारे में चिंतित हैं कर सकते हैं।

+0

मुझे लगता है कि आप मेरे कोड का उपयोग कर रहे हैं क्योंकि तर्क मूल्य है, लेकिन बिटकोनवर्टर। DoubleToInt64Bits तर्क के रूप में "डी" हो जाता है। मुझे केवल एक जोड़ने के बारे में आरक्षण था क्योंकि आईईईई प्रारूप एक्सपोनेंट और महत्व को अलग करता है, लेकिन क्योंकि इसमें एक छिपी हुई बिट है, इसलिए आपका कार्य वास्तव में ठीक है, जहां तक ​​मैं देख सकता हूं। –

6

अधिकांश भाषाओं में अगले या पिछले एकल-परिशुद्धता (32-बिट) और/या डबल-परिशुद्धता (64-बिट) संख्या प्राप्त करने के लिए आंतरिक या लाइब्रेरी फ़ंक्शन होते हैं।

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

मैंने सी # और सी ++ के लिए समाधान देखा। यहाँ जावा के लिए कुछ कर रहे हैं:

Math.nextUp:

सार्वजनिक स्थैतिक डबल nextUp (डबल घ):

  • की दिशा में घ के निकट फ्लोटिंग प्वाइंट मान देता है सकारात्मक अनंतता। यह विधि semantically के बराबर है इसके बाद (डी, डबल। POSITIVE_INFINITY); हालांकि, अगली अप कार्यान्वयन इसके समकक्ष अगली कॉल के बाद तेजी से चल सकता है।

विशेष मामले:

  • तो तर्क NaN है, परिणाम NaN है।
  • यदि तर्क सकारात्मक अनंत है, तो परिणाम सकारात्मक अनंत है।
  • तर्क शून्य है, परिणाम Double.MIN_VALUE
  • है

पैरामीटर:

  • घ - शुरू करने फ़्लोटिंग-बिंदु मान

रिटर्न:

  • आसन्न फ्लोटिंग-पॉइंट वैल्यू सकारात्मक अनंतता के करीब है।

सार्वजनिक स्थिर नाव nextUp (नाव च):

  • रिटर्न सकारात्मक अनंत की दिशा में च से सटे फ़्लोटिंग-बिंदु मान। यह विधि semantically के बराबर है (एफ, Float.POSITIVE_INFINITY); हालांकि, अगली अप कार्यान्वयन इसके समकक्ष अगली कॉल के बाद तेजी से चल सकता है।

विशेष मामले:

  • तो तर्क NaN है, परिणाम NaN है।
  • यदि तर्क सकारात्मक अनंत है, तो परिणाम सकारात्मक अनंत है।
  • तर्क शून्य है, परिणाम Float.MIN_VALUE है

पैरामीटर:

  • च - शुरू करने फ़्लोटिंग-बिंदु मान

रिटर्न:

  • आसन्न फ्लोटिंग-पॉइंट वैल्यू सकारात्मक अनंतता के करीब है।

अगले दो उपयोग करने के लिए थोड़ा अधिक जटिल हैं। हालांकि, शून्य या दिशात्मक या नकारात्मक अनंतता की दिशा में एक दिशा अधिक संभावना और उपयोगी उपयोग प्रतीत होती है। एक और उपयोग दो मानों के बीच एक मध्यवर्ती मान मौजूद है। कोई यह निर्धारित कर सकता है कि लूप और काउंटर के साथ दो मानों के बीच कितने मौजूद हैं। साथ ही, ऐसा लगता है कि वे अगली अप विधियों के साथ, लूप के लिए वृद्धि/कमी के लिए उपयोगी हो सकते हैं।

Math.nextAfter :

सार्वजनिक स्थैतिक डबल nextAfter (डबल शुरू, डबल दिशा)

  • की दिशा में पहला तर्क से सटे फ्लोटिंग प्वाइंट संख्या देता है दूसरा तर्क। यदि दोनों तर्क के बराबर तुलना करते हैं तो दूसरा तर्क वापस आ जाता है।

विशेष मामलों: या तो तर्क एक NaN है

  • , तो NaN दिया जाता है।
  • यदि दोनों तर्क शून्य पर हस्ताक्षर किए गए हैं, तो दिशापर वापस आती है (जैसा कि तर्कों के बराबर तुलना करता है तो दूसरा तर्क लौटने की आवश्यकता के अनुसार)।
  • यदि प्रारंभ है ± Double.MIN_VALUE और दिशा में एक मान है कि परिणाम में एक छोटी परिमाण होनी चाहिए, तो उसी हस्ताक्षर के साथ एक शून्य शून्य के रूप में हस्ताक्षर किया जाना चाहिए।
  • यदि प्रारंभ अनंत है और दिशा में एक मान है कि परिणाम में एक छोटा आयाम होना चाहिए, तो उसी संकेत के साथ डबल .MAX_VALUE प्रारंभ होना चाहिए।
  • यदि प्रारंभ ± Double.MAX_VALUE के बराबर है और दिशा का मूल्य है, तो परिणामस्वरूप एक बड़ी परिमाण होनी चाहिए, के साथ एक अनंतता प्रारंभ होने के समान ही संकेत होनी चाहिए।

पैरामीटर:

  • शुरू - शुरू करने फ़्लोटिंग-बिंदु मान
  • दिशा - मूल्य का संकेत है जो शुरुआत के पड़ोसियों के या शुरू

रिटर्न लौटे किया जाना चाहिए:

  • फ़्लोटिंग पॉइंट दिशा की दिशा में शुरू होने के निकट संख्या।

सार्वजनिक स्थिर नाव nextAfter (नाव शुरू, डबल दिशा)

  • में दूसरा तर्क की दिशा पहला तर्क से सटे फ्लोटिंग प्वाइंट संख्या देता है। यदि दोनों तर्क के रूप में तुलना करते हैं तो दूसरे तर्क के बराबर मान बराबर होता है।

विशेष मामलों: या तो तर्क एक NaN है

  • , तो NaN दिया जाता है।
  • यदि दोनों तर्क शून्य पर हस्ताक्षर किए गए हैं, तो दिशा के बराबर मान वापस कर दिया गया है।
  • यदि प्रारंभ है ± Float.MIN_VALUE और दिशा में एक मान है कि परिणाम में एक छोटी परिमाण होनी चाहिए, तो उसी हस्ताक्षर के साथ एक शून्य शून्य शुरू हो जाएगा।
  • यदि प्रारंभ अनंत है और दिशा में एक मान है कि परिणाम में एक छोटी परिमाण होनी चाहिए, तो फ्लोट.एमएक्स_वीएमएल उसी संकेत के साथ शुरू हो जाना चाहिए।
  • यदि प्रारंभ ± Float.MAX_VALUE के बराबर है और दिशा में का मान है, तो परिणाम में एक बड़ी परिमाण होनी चाहिए, उसी संकेत के साथ एक अनंतता वापस लौटा दी गई है।

पैरामीटर:

  • शुरू - शुरू करने फ़्लोटिंग-बिंदु मान
  • दिशा - मूल्य शुरुआत के पड़ोसियों के जो यह दर्शाता है या शुरू

रिटर्न लौटे किया जाना चाहिए:

  • फ्लोटिंग-पॉइंट नंबर में शुरू होने के निकट दिशा की दिशा।
1

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

निकट मूल्यों के लिए (दशमलव मानों की विशाल सीमा के सापेक्ष निकट डबल्स का प्रतिनिधित्व कर सकते हैं) 1 या -1, ईपीएसलॉन शून्य या बहुत छोटा होगा। उन मूल्यों के लिए जो प्रगतिशील रूप से + या - अनंत या शून्य की ओर बढ़ते हैं, ईपीएसलॉन बढ़ने लगेंगे। शून्य या बहुत अनंत के करीब मूल्यों पर, ईपीएसलॉन बहुत बड़ा होगा क्योंकि उन श्रेणियों में दशमलव मानों के लिए उपलब्ध बाइनरी प्रस्तुतियां बहुत ही दुर्लभ हैं।