2010-06-05 16 views
87

यह कुछ ऐसा है जो मेरे दिमाग में वर्षों से रहा है, लेकिन मैंने पहले कभी पूछने का समय नहीं लिया।0.0 और 1.0 के बीच कितने डबल नंबर हैं?

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

तो प्रश्न हैं:

  1. बस कितने double संख्या 0.0 और 1.0 के बीच देखते हैं?
  2. क्या 1 और 2 के बीच की संख्या बहुत अधिक है? 100 और 101 के बीच? 10^100 और 10^100 + 1 के बीच?

नोट: यदि यह कोई फर्क पड़ता है, तो मुझे विशेष रूप से double की जावा की परिभाषा में रूचि है।

उत्तर

60

जावा double एस IEEE-754 प्रारूप में हैं, इसलिए उनके पास 52-बिट अंश है; दो की किसी भी दो आसन्न शक्तियों (एक के साथ और अगले एक के अनन्य) के बीच, इसलिए 52 वीं शक्ति के लिएएस (यानी, 4503599627370496) अलग-अलग होंगे। उदाहरण के लिए, यह 0.5 शामिल और 1.0 के बीच अलग double एस की संख्या है, और वास्तव में बहुत से 1.0 शामिल हैं और 2.0 को छोड़कर, और आगे भी।

0.0 और 1.0 के बीच doubles की गणना करना दो की शक्तियों के बीच ऐसा करने से कठिन है, क्योंकि उस श्रेणी में दो की कई शक्तियां शामिल हैं, और साथ ही, किसी को असामान्य संख्याओं के कांटेदार मुद्दों में शामिल किया जाता है। एक्सपोनेंट्स के 11 बिट्स में से 10 में सवाल की सीमा शामिल है, इसलिए, डिमॉर्मलाइज्ड नंबरों सहित (और मुझे लगता है कि कुछ प्रकार के NaN) आपके पास double एस की 1024 गुणा होगी जो कि दो की शक्तियों के बीच है - 2**62 से अधिक नहीं वैसे भी कुल मिलाकर। Denormalized & सी को छोड़कर, मुझे विश्वास है कि गणना 1023 बार 2**52 होगी।

"100.1 करने के लिए 100" की तरह एक मनमाना सीमा के लिए यह और भी कठिन है क्योंकि ऊपरी बाध्य वास्तव में एक double (दोनों में से किसी भी बिजली की एक सटीक एकाधिक नहीं किया जा रहा) के रूप में प्रतिनिधित्व नहीं किया जा सकता है।एक आसान सन्निकटन के रूप में, के बाद से दो की शक्तियों के बीच प्रगति रैखिक है, तो आप कह सकते हैं कि कहा रेंज दो (64 और 128) के आसपास के शक्तियों के बीच अवधि के 0.1/64 वीं है, तो आप के बारे में

(0.1/64) * 2**52 
उम्मीद थी

विशिष्ट double एस - जो 7036874417766.4004 पर आता है ... एक या दो दें ;-)।

+0

@Alex: बस ध्यान दें, जब मैंने 100 से 100.1 लिखा था तो मैंने गलत लिखा था। मेरा मतलब 100 से 101 था। असल में, एन और एन + 1 के बीच मनमाने ढंग से एन – polygenelubricants

+4

@ एलेक्स: तो मुझे यह सीधे प्राप्त करने दें: '2 ** 64' संभव डबल मानों से अधिक नहीं हो सकता है (क्योंकि यह 64 बिट है प्रकार), और स्पष्ट रूप से उन मानों का एक बड़ा हिस्सा '0..1' के बीच है? – polygenelubricants

+9

@ पोलीजिन, हां और हां - विशेष रूप से, संभव मूल्यों के लगभग एक चौथाई (किसी भी आधार और एक्सपोनेंट बनाम अंश लंबाई के किसी भी "सामान्य" फ़्लोटिंग पॉइंट प्रस्तुति के लिए) 0.0 और 1.0 के बीच है (1.0 और अनंत के बीच एक और तिमाही, और असली धुरी के नकारात्मक आधे भाग पर शेष आधा)। अनिवार्य रूप से, एक्सपोनेंट के आधे मूल्य (सामान्य पूर्वाग्रह के साथ, इसकी सीमा के भीतर आधे रास्ते) आधार की नकारात्मक शक्तियों का प्रतिनिधित्व करते हैं, इसलिए संख्या <1.0। –

2
  1. 2^53 - छिपे हुए बिट सहित 64 बिट फ्लोटिंग पॉइंट नंबर के महत्व/मंटिसा का आकार।
  2. काफी हां, क्योंकि सिफनिफिश तय है लेकिन एक्सपोनेंट परिवर्तन।

अधिक जानकारी के लिए wikipedia article देखें।

+0

2 प्रतिक्रियाओं के लिए आपका उत्तर मैं एफपी के काम को कैसे समझता हूं। – polygenelubricants

+0

मुझे लगता है कि '1' गलत है क्योंकि छिपी हुई बिट हमेशा एक है - इसलिए,' 2^52', ** नहीं ** '2^53' _distinct_ मान (दो की आसन्न शक्तियों के बीच, एक शामिल है और अगला वाला बहिष्कृत - ** नहीं ** 0.0 और 1.0 के बीच!)। –

3

आईबीएम से लेख Java's new math, Part 2: Floating-point numbers इस हल करने के लिए निम्नलिखित कोड का टुकड़ा प्रदान करता है (तैरता में है, लेकिन मुझे लगता है यह रूप में अच्छी तरह डबल्स के लिए काम करता है):

:

public class FloatCounter { 

    public static void main(String[] args) { 
     float x = 1.0F; 
     int numFloats = 0; 
     while (x <= 2.0) { 
      numFloats++; 
      System.out.println(x); 
      x = Math.nextUp(x); 
     } 
     System.out.println(numFloats); 
    } 
} 

उन्हें इसके बारे में यह टिप्पणी की है

यह पता चला है कि 1.0 और 2.0 के बीच बिल्कुल 8,388,60 9 फ्लोट हैं; इस सीमा में मौजूद वास्तविक संख्याओं की बड़ी लेकिन शायद ही अनजान अनंतता। लगातार संख्या लगभग 0.0000001 अलग हैं। इस दूरी को अंतिम स्थान पर कम से कम परिशुद्धता या इकाई की इकाई के लिए एक यूएलपी कहा जाता है।

+0

हाँ, लेकिन यह 'फ्लोट' के लिए है, _not_ 'double' -' फ्लोट के पास 23 बिट्स का अंश है, इसलिए '2 ** 23 -> 8388608 'दो की आसन्न शक्तियों के बीच अलग-अलग मान (" समावेशी " निश्चित रूप से इसका मतलब है कि आपको एक और गिनना होगा, अगली शक्ति दो)। 'डबल की 52-बिट भिन्नताएं हैं! –

+1

@Alex: मुझे लगता है कि मुझे ब्रह्मांड के अंत तक चलने वाले कार्यक्रम (युगल के लिए संशोधित) छोड़ना होगा या इससे पहले कि मैं परिणाम प्राप्त कर सकूं ... :( –

+1

मुझे गूंगा लगता है; मैंने अभी 'डबल' लिखा है 'समकक्ष और सोचा" अरे, मैं अपने 5 प्रश्नों में अपने प्रश्न का उत्तर दूंगा ... " – polygenelubricants

1

जावा डबल आईईईई 754 बाइनरी 64 नंबर है।

इसका मतलब है कि हम इस पर विचार करने की जरूरत है:

  1. अपूर्णांश 52 बिट
  2. घातांक है 1023 पूर्वाग्रह के साथ 11 बिट संख्या
  3. (यानी 1023 के साथ यह करने के लिए जोड़ा) प्रतिपादक सभी 0 है, तो है और मंथिसा शून्य नहीं है तो संख्या को गैर-सामान्यीकृत

मूल रूप से इसका मतलब है कि कुल दो^62-2^52 + 1 संभव डबल प्रस्तुतियों के हैं जो मानक के अनुसार मानक हैं ईन 0 और 1. ध्यान दें कि गैर-सामान्यीकृत संख्याओं के मामलों को हटाने के लिए 2^52 + 1 है।

याद रखें कि यदि अपूर्णांश सकारात्मक है लेकिन प्रतिपादक नकारात्मक संख्या सकारात्मक लेकिन कम से कम 1 :-) है

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

35

प्रत्येक double मूल्य जिसका प्रतिनिधित्व 0x0000000000000000 और 0x3ff0000000000000 अंतराल [0.0, 1.0] में है। यह है (2^62 - 2^52) अलग-अलग मान (प्लस या शून्य जो कि आप अंत बिंदुओं को गिनते हैं) पर निर्भर करता है।

अंतराल [1.0, 2.0] 0x3ff0000000000000 और 0x400000000000000 के बीच प्रतिनिधित्व के अनुरूप है; वह 2^52 विशिष्ट मान है।

अंतराल [100.0, 101.0] 0x4059000000000000 और 0x4059400000000000 के बीच प्रतिनिधित्व के अनुरूप है; वह 2^46 विशिष्ट मान है।

10^100 और 10^100 + 1 के बीच कोई युगल नहीं है। न तो उन संख्याओं में से एक डबल परिशुद्धता में प्रतिनिधित्व योग्य है, और उनके बीच कोई युगल नहीं है। निकटतम दो डबल परिशुद्धता नंबर दिए गए हैं:

99999999999999982163600188718701095... 

और

10000000000000000159028911097599180... 
+0

+1। (यदि आप एंडपॉइंट्स को गिनने के बारे में चुनिंदा हैं, तो याद रखें कि +0.0 और -0.0 में अलग-अलग प्रतिनिधित्व हैं।) –

+1

+1, इस तरह की मोड़ खत्म! ऐसा लगता है कि मैं एम। नाइट श्यामलन लिपि पढ़ रहा था! – polygenelubricants

6

दूसरों को पहले से ही समझा दिया रेंज [0.0, 1.0] में 2^62 युगल चारों ओर देखते हैं कि।
(वास्तव में नहीं आश्चर्य की बात: वहाँ लगभग 2^64 अलग परिमित युगल हैं, उन में से आधे सकारात्मक, और के लगभग आधे उन < 1.0 कर रहे हैं।)

लेकिन तुम यादृच्छिक संख्या जनरेटर का उल्लेख: ध्यान दें एक है कि 0.0 और 1 के बीच यादृच्छिक संख्या जनरेटर जनरेटिंग संख्या।0 इन सभी संख्याओं के सामान्य उत्पादन में नहीं कर सकते हैं; आम तौर पर यह केवल एक पूर्णांक के साथ फॉर्म n/2^53 की संख्या उत्पन्न करेगा (उदाहरण के लिए nextDouble के लिए जावा दस्तावेज़ देखें)। इसलिए random() आउटपुट के लिए आमतौर पर केवल 2^53 (+/- 1, जो अंत बिंदुओं को शामिल किया जाता है) के संभावित मूल्य होते हैं। इसका मतलब है कि [0.0, 1.0] में अधिकांश युगल कभी उत्पन्न नहीं होंगे।

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