2009-02-08 14 views
5

क्या फ्लोट एचटी पढ़ने और एएनएसआई सी का उपयोग किए बिना पोर्टेबल तरीके से फ्लोट, डबल और लंबे डबल डेटा प्रकारों की श्रेणियों की गणना करना संभव है? पोर्टेबल द्वारा, मेरा मतलब है उन मामलों सहित जब लक्ष्य मशीन आईईईई 754 मानक का पालन नहीं करती है।फ़्लोटिंग पॉइंट डेटा प्रकारों की श्रेणियों की गणना

मैं कश्मीर & आर पुस्तक और व्यायाम 2-1 पढ़ रहा हूँ मुझे पूछते हैं, "गणना" करने के लिए उन्हें ऐसा मुझे लगता है कि पूरी तरह से जो भी शामिल है FLT_MIN, FLT_MAX, DBL_MIN और DBL_MAX (इन मूल्यों को सीधे होगा पढ़ने float.h से बचने का मतलब निश्चित रूप से "कंप्यूटिंग" के रूप में वर्गीकृत नहीं है)।

+0

आपको लगता है कि फ्लोट.h से बचने का मतलब क्यों है? अच्छा मुझे लगता है कि यह चाहता है कि आप कुछ फ़ंक्शन जैसे ldexp, FLT_RADIX (या जिसे भी कहा जाता है) और सामग्री –

+0

अच्छी तरह से उपयोग करें, क्योंकि float.h में पहले से ही न्यूनतम/अधिकतम मान उपलब्ध हैं जो इस मामले में धोखाधड़ी की तरह लगेंगे। लेकिन हाँ, float.h में परिभाषित कुछ अन्य स्थिरांक हैं जो संभवतः वास्तविक श्रेणियों को निर्धारित करने के लिए उपयोग किए जा सकते हैं। – Ree

उत्तर

3
एक ज़रूरत से ज़्यादा जवाब के जोखिम पर

। यही कारण है कि <float.h> हेडर प्रदान किया गया है - क्योंकि इसमें निहित जानकारी प्राप्त करने के लिए कोई पोर्टेबल तरीका नहीं है।

+2

के लिए काम करता है यह सच है - लेकिन ऐसी गणनाएं हैं जो एन्कोडिंग योजनाओं की एक विस्तृत श्रृंखला के लिए काम करेंगे! – Christoph

2

आप इसे तब तक फ़्लोट करने की कोशिश कर सकते हैं जब तक यह बहती न हो।

+0

यही वह है जो मैं पूर्णांक प्रकारों के साथ कर रहा हूं - लेकिन इसमें लंबे समय तक बहने में काफी समय नहीं लगेगा? – Ree

+0

यदि आप इसे घातीय खोज से करते हैं, तो यह पर्याप्त तेज़ी से बह जाएगा। आप संख्या को तेज़ी से बढ़ने के लिए भी कर सकते हैं (उदाहरण के लिए अधिकतम मूल्य की अधिकतम घातीय बनाम घातीय खोज की घातीय खोज) – jpalecek

4

सभी अनुप्रयोगों के 99.99% के लिए, आपको आईईईई 754 मानना ​​चाहिए और <float.h> में परिभाषित स्थिरांक का उपयोग करना चाहिए। अन्य 0.01% में, आप बहुत विशिष्ट हार्डवेयर के साथ काम करेंगे, और उस स्थिति में, आपको पता होना चाहिए कि हार्डवेयर के आधार पर क्या उपयोग करना है।

11

यह (कम से कम आईईईई 754 float और double मूल्यों के लिए) (छद्म कोड) के माध्यम से सबसे बड़ी फ्लोटिंग प्वाइंट मूल्य की गणना करने के लिए संभव है:

~(-1.0) | 0.5 

इससे पहले कि हम हमारे बिट twiddling कर सकते हैं, हम फ्लोटिंग-पॉइंट मानों को पूर्णांक में परिवर्तित करना होगा और फिर फिर से वापस करना होगा। यह निम्न तरीके से किया जा सकता है:

uint64_t m_one, half; 
double max; 

*(double *)(void *)&m_one = -1.0; 
*(double *)(void *)&half = 0.5; 
*(uint64_t *)(void *)&max = ~m_one | half; 

तो यह कैसे काम करता है? इसके लिए, हमें यह जानना होगा कि फ़्लोटिंग-पॉइंट मान कैसे एन्कोड किए जाएंगे।

उच्चतम बिट साइन को एन्कोड करता है, अगले k बिट्स एक्सपोनेंट को एन्कोड करते हैं और निम्नतम बिट्स आंशिक भाग को पकड़ेंगे। 2 की शक्तियों के लिए, आंशिक भाग 0 है।

एक्सपोनेंट 2**(k-1) - 1 के पूर्वाग्रह (ऑफ़सेट) के साथ संग्रहीत किया जाएगा, जिसका अर्थ है 0 का एक एक्सपोनेंट सभी के साथ एक पैटर्न के अनुरूप है लेकिन उच्चतम बिट सेट के साथ है।

वहाँ विशेष अर्थ के साथ दो प्रतिपादक बिट पैटर्न हैं:

  • अगर कोई थोड़ा सेट किया गया है, मूल्य 0 हो सकता है अगर आंशिक हिस्सा शून्य है; अन्यथा, मूल्य एक सामान्य से कम
  • सभी बिट्स सेट कर रहे हैं, मूल्य या तो infinity या NaN

इसका मतलब यह है सबसे बड़ी नियमित प्रतिपादक सबसे कम है, जो से मेल खाती है के अलावा सभी बिट्स की स्थापना के माध्यम से इनकोडिंग हो जाएगा है यदि आप पूर्वाग्रह को घटाते हैं तो 2**k - 2 या 2**(k-1) - 1 का मान।

double के लिए मूल्यों, k = 11, यानी उच्चतम प्रतिपादक 1023 हो जाएगा, तो सबसे बड़ी चल बिन्दु मूल्य आदेश 2**1023 है जो 1E+308 के बारे में है।

सबसे ज्यादा मूल्य

  • संकेत बिट 0
  • सब करने के लिए सेट लेकिन सबसे कम प्रतिपादक बिट 1
  • करने के लिए सभी आंशिक बिट्स अब 1

करने के लिए सेट सेट करना होगा, यह समझना संभव है कि हमारे जादू संख्या कैसे काम करती हैं:

  • -1.0 इसके संकेत बिट सेट है, प्रतिपादक पूर्वाग्रह है - यानी सभी बिट्स लेकिन उच्चतम एक मौजूद हैं - और आंशिक भाग 0
  • ~(-1.0) केवल उच्चतम प्रतिपादक सा है और सभी आंशिक बिट्स
  • सेट किया गया है
  • 0.5 में 0 का एक साइन बिट और fractional हिस्सा है; प्रतिपादक पूर्वाग्रह शून्य से 1 हो जाएगा, यानी सभी लेकिन उच्चतम और निम्नतम प्रतिपादक बिट्स वर्तमान

जब हम तार्किक के माध्यम से इन दो मानों गठबंधन होगा या, हम सा पैटर्न हम चाहते थे मिल जाएगा।


गणना 86 80-बिट बढ़ाया परिशुद्धता मूल्यों (उर्फ long double) के साथ के लिए काम करता है, लेकिन थोड़ा-twiddling बाइट के लिहाज से किया जाना चाहिए के रूप में कोई पूर्णांक प्रकार इतना बड़ा 32- पर मान धारण करने के लिए बिट हार्डवेयर।

पूर्वाग्रह वास्तव में 2**(k-1) - 1 होने की आवश्यकता नहीं है - यह एक मनमाना पूर्वाग्रह के लिए काम करेगा जब तक कि यह विषम है। पूर्वाग्रह अजीब होना चाहिए क्योंकि अन्यथा 1.0 और 0.5 के एक्सपोनेंट के लिए बिट-पैटर्न सबसे कम बिट की तुलना में अन्य स्थानों में भिन्न होंगे।

तो आधार b (उर्फ मूलांक) फ्लोटिंग प्वाइंट प्रकार के 2 नहीं है, आप b**(-1) बजाय 0.5 = 2**(-1) उपयोग करना होगा।

यदि सबसे बड़ा एक्सपोनेंट मान reserverd नहीं है, तो 0.5 के बजाय 1.0 का उपयोग करें। यह आधार या पूर्वाग्रह के बावजूद काम करेगा (जिसका अर्थ है कि यह अब अजीब मानों तक सीमित नहीं है)। 1.0 का उपयोग करने में अंतर यह है कि सबसे कम एक्सपोनेंट बिट साफ़ नहीं किया जाएगा।


संक्षेप में:

~(-1.0) | 0.5 

जब तक मूलांक 2 है काम करता है, पूर्वाग्रह विषम है और उच्चतम प्रतिपादक आरक्षित है।

~(-1.0) | 1.0 

किसी भी रेडिक्स या पूर्वाग्रह के लिए काम करता है जब तक कि उच्चतम एक्सपोनेंट आरक्षित न हो।

नहीं। वहाँ एक पोर्टेबल पर्वतमाला की गणना करने के लिए रास्ता नहीं है:

+0

"आईईईई 754 के लिए" कहने से सवाल का आधार अस्वीकार कर दिया गया है। –

+1

@ जोनाथन: 'कम से कम' के लिए 'केवल' के लिए 'कम से कम' मतलब नहीं है - यह '2 ** (के -1) - 1' की पूर्वाग्रह के साथ प्रत्येक फ़्लोटिंग-पॉइंट मान के लिए काम करता है और' 2 का आरक्षित एक्सपोनेंट ** के -1 1, जिसमें x86 – Christoph

+1

@Jonathan पर आधे और चौगुनी सटीक मानों के साथ-साथ 80-बिट विस्तारित सटीक मान शामिल हैं: यदि आप संभव एन्कोडिंग योजनाओं को प्रतिबंधित नहीं करते हैं तो आप कुछ और 'गणना' करना चाहते हैं? वहां एक एल्गोरिदम नहीं है जो सभी एन्कोडिंग के लिए काम करेगा! – Christoph

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