2015-11-16 7 views
6

पर रूपांतरण द्वारा लंबे समय तक अग्रणी शून्य ढूंढना Long.numberOfLeadingZeros(long i) विधि ढूंढने से पहले, मैं युगल के लिए लंबे समय तक कास्टिंग कर रहा था और Math.getExponent(double d) का उपयोग कर रहा था। विचार लंबे समय के दोहरे प्रतिनिधित्व को खोजने के लिए था, उच्चतम सेट बिट प्राप्त करने के लिए एक्सपोनेंट का उपयोग करें, और अग्रणी शून्यों की संख्या प्राप्त करने के लिए इसे 64 से घटाएं।जावा - डबल

यह ज्यादातर 1. द्वारा बंद काम किया, लेकिन कभी-कभी था निम्नलिखित के लिए लूप समस्या को हाइलाइट करने के लिए इस्तेमाल किया गया था:

for (int i = 0; i < 64; i++) { 
    double max = Long.MAX_VALUE >>> i; 
    double min = Long.MIN_VALUE >>> i; 
    double neg = -1L >>> i; 
    System.out.format("Max: %-5d Min: %-5d -1: %-5d%n", Math.getExponent(dmax), 
           Math.getExponent(dmin), Math.getExponent(dneg)); 
} 
उत्पादन का महत्वपूर्ण भाग के साथ

:

... 
Max: 55 Min: 55 -1: 56 
Max: 54 Min: 54 -1: 55 
Max: 52 Min: 53 -1: 54 
Max: 51 Min: 52 -1: 52 
Max: 50 Min: 51 -1: 51 
... 

देशांतर सभी बिट्स सेट 1^52 से ऊपर 1 से बंद हैं। As this post explains, 52-बिट मंटिसा में 53+ महत्वपूर्ण बिट्स के संग्रहण के कारण परिशुद्धता का नुकसान होता है। हालांकि, मैं समझने के लिए संघर्ष कर रहा हूं कि एक्सपोनेंट क्यों प्रभावित होता है।

जबकि मैं अब इस विधि का उपयोग नहीं कर रहा हूं, मैं अभी भी उत्सुक हूं: क्यों और किस परिस्थितियों में लंबे समय तक अग्रणी शून्य खोजने की विधि विफल होती है?

उत्तर

3

एक double पर परिशुद्धता की सीमा 2 के निकटतम शक्ति है, जो double मूल्य की फ्लोटिंग प्वाइंट प्रतिनिधित्व में वृद्धि कर देता है प्रतिपादक में इसे राउंड के लिए द्विआधारी प्रतिनिधित्व बाध्य करती है। ऐसा इसलिए होता है क्योंकि अंतर्निहित 1 बिट सहित डबल की मंटिसा 53 बिट्स है, लेकिन long में 64 बिट हैं।

Section 5.1.2 of the JLS को शामिल किया गया है कि इस चौड़ा आदिम रूपांतरण में हो सकता है:

पूर्णांक से एक को चौड़ा आदिम रूपांतरण फ्लोट करने के लिए, या लंबे समय से फ्लोट करने के लिए, या लंबे समय से दोगुना करने के लिए, सटीक की हानि हो सकती है - कि है, परिणाम मूल्य के कम से कम महत्वपूर्ण बिट्स खो सकता है। इस मामले में, परिणामस्वरूप फ़्लोटिंग-पॉइंट मान इंटीजर मान का सही गोलाकार संस्करण होगा, आईईईई 754 राउंड-टू-नजदीकी मोड (§4.2.4) का उपयोग करके।

(जोर मेरा)

यहाँ, मैं Double.doubleToLongBits का प्रयोग कर एक long में एक double के टुकड़े को बचाने के लिये, और Long.toHexString मूल double के स मान बाहर मुद्रित करने के लिए।

System.out.format("Max(%s): %-5d Min(%s): %-5d -1(%s): %-5d%n", 
       Long.toHexString(Double.doubleToLongBits(dmax)), Math.getExponent(dmax), 
       Long.toHexString(Double.doubleToLongBits(dmax)), Math.getExponent(dmin), 
       Long.toHexString(Double.doubleToLongBits(dneg)), Math.getExponent(dneg)); 

आउटपुट:

Max(43e0000000000000): 63 Min(43e0000000000000): 63 -1(bff0000000000000): 0  
Max(43d0000000000000): 62 Min(43d0000000000000): 62 -1(43e0000000000000): 63 
Max(43c0000000000000): 61 Min(43c0000000000000): 61 -1(43d0000000000000): 62 
Max(43b0000000000000): 60 Min(43b0000000000000): 60 -1(43c0000000000000): 61 
Max(43a0000000000000): 59 Min(43a0000000000000): 59 -1(43b0000000000000): 60 
Max(4390000000000000): 58 Min(4390000000000000): 58 -1(43a0000000000000): 59 
Max(4380000000000000): 57 Min(4380000000000000): 57 -1(4390000000000000): 58 
Max(4370000000000000): 56 Min(4370000000000000): 56 -1(4380000000000000): 57 
Max(4360000000000000): 55 Min(4360000000000000): 55 -1(4370000000000000): 56 
Max(4350000000000000): 54 Min(4350000000000000): 54 -1(4360000000000000): 55 
Max(433fffffffffffff): 52 Min(433fffffffffffff): 53 -1(4350000000000000): 54 
Max(432ffffffffffffe): 51 Min(432ffffffffffffe): 52 -1(433fffffffffffff): 52 

मूल long से अधिक 53 1 बिट्स के साथ मूल्यों को गिरफ्तार कर रहे हैं जब एक double में बदला, सटीक खोने। एक्सपोनेंट फ़ील्ड में बिट्स 212 के माध्यम से ऊपर दिए गए पहले 3 हेक्स अंकों में दिखाई देता है।

जब मूल्य 53 1 बिट्स नीचे स्थानांतरित कर दिया है, double की परिशुद्धता अब गोलाई के बिना मूल्य धारण करने के लिए पर्याप्त है (दौर ऊपर कोई आवश्यकता नहीं है) और अपूर्णांश के बिट्स के रूप में दिखाई देने लगते हैं 'एफ' हेक्स अंक।435 से 433 पर एक्सपोनेंट फ़ील्ड में एक असंतोष है, यह बताते हुए कि Math.getExponent के परिणामस्वरूप 54 से 52 के परिणामस्वरूप एक असंतुलन क्यों है।

+0

यह सही समझ में आता है। अपनी पोस्ट पढ़ने के बाद, मैंने अपने 11 कम से कम महत्वपूर्ण बिट्स को ड्रॉप करने के लिए 2^53 - 1 से अधिक मूल्यों को मजबूर किया: 'value & = 0xFFFFFFFFFFFFF700L;' एक डबल से रूपांतरण से पहले, अनावश्यक गोल करना। मैं भी भूल गया कि मंटिसा में अतिरिक्त अंतर्निहित बिट है। विस्तृत उत्तर के लिए धन्यवाद! –

1

कम जगहों पर गोल होने पर सभी के साथ एक संख्या गोलाकार हो जाएगी और इसलिए एक और लंबा हो जाएगा। उदाहरण के लिए (मान एक डबल अपूर्णांश में केवल 5 बिट्स है) जब गोल

111111 becomes 1000000 

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