2012-01-19 11 views
8

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

हालांकि, सिस्टम के कुछ हिस्सों में यह युगल के साथ काम करने की पठनीयता के कारण अधिक सुविधाजनक है। तो हमें 9 दशमलव स्थानों को डबल में मानने वाले लंबे मूल्य के बीच रूपांतरित करना होगा।

हम 9 की शक्ति के लिए 10 तक लंबी और विभाजित करते हैं या 1 से गुणा करके 10 की शक्ति से 10 गुणा में अपूर्ण प्रस्तुतिकरण देते हैं।

यह हल करने के लिए कि हम सटीक मान देने के लिए Math.Round(value,9) का उपयोग कर रहे हैं।

हालांकि, Math.Round() प्रदर्शन के लिए बहुत धीमी गति से धीमा है।

तो इस समय हमारा विचार सीधे मोंटिसा और एक्सपोनेंट को दोहरी के बाइनरी प्रारूप में परिवर्तित करना है - इस तरह, गोल करने के लिए शून्य आवश्यकता होगी।

हमने ऑनलाइन सीख लिया है कि मंटिसा और एक्सपोनेंट प्राप्त करने के लिए दोगुनी बिट्स की जांच कैसे करें, लेकिन यह समझने में भ्रमित है कि मंटिसा और एक्सपोनेंट लेने के लिए इसे कैसे उलटना है और बिट्स का उपयोग करके दोहराएं।

कोई सुझाव?

[Test] 
public unsafe void ChangeBitsInDouble() 
{ 
    var original = 1.0D; 
    long bits; 
    double* dptr = &original; 
    //bits = *(long*) dptr; 
    bits = BitConverter.DoubleToInt64Bits(original); 
    var negative = (bits < 0); 
    var exponent = (int) ((bits >> 52) & 0x7ffL); 
    var mantissa = bits & 0xfffffffffffffL; 
    if(exponent == 0) 
    { 
     exponent++; 
    } 
    else 
    { 
     mantissa = mantissa | (1L << 52); 
    } 
    exponent -= 1075; 

    if(mantissa == 0) 
    { 
     return; 
    } 

    while ((mantissa & 1) == 0) 
    { 
     mantissa >>= 1; 
     exponent++; 
    } 

    Console.WriteLine("Mantissa " + mantissa + ", exponent " + exponent); 

} 
+3

क्या आप सुनिश्चित हैं कि आपके पास मूल्य 'डबल' में बिल्कुल सही है? – Justin

+0

शायद यह मदद करेगा, मैं इसे आपकी मदद करने के लिए बस इसे पढ़ना नहीं चाहता हूं: पी http://steve.hollasch.net/cgindex/coding/ieeefloat.html – MrFox

उत्तर

1

आपको 10^9 के स्केल फैक्टर का उपयोग नहीं करना चाहिए, आपको इसके बजाय 2^30 का उपयोग करना चाहिए।

+0

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

+0

यह लंबे प्रतिनिधित्व को अपठनीय बना देगा लेकिन प्रदर्शन में काफी सुधार करेगा और दोबारा रूपांतरण वापस तेजी से हल्का होगा। तो यह एक उत्कृष्ट व्यापार है। धन्यवाद! – Wayne

+0

वैसे यह तार्किक लगता है लेकिन कारक द्वारा विभाजित करने के बाद परीक्षण में विभाजित करने के बाद यह अपर्याप्त होता है: var convert = 1 << 30; डबल मूल्य = 45.454945768 डी; लंबा परिणाम 1 = (लंबा) (मूल्य * रूपांतरित); डबल परिणाम 2 = ((डबल) परिणाम 1)/रूपांतरित करें; Assert.AreEqual (परिणाम 2, मूल्य); – Wayne

0

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

यह भी स्पष्ट नहीं है कि यह जानबूझकर सरलीकृत सूत्र के साथ काम कर सकता है, क्योंकि यह स्पष्ट नहीं है कि आपको अधिकतम सीमा क्या है, इसलिए गोल करना अनिवार्य हो जाता है।

इतनी जल्दी करने की समस्या लेकिन ठीक से अध्ययन किया जाता है और अक्सर सीपीयू निर्देशों द्वारा समर्थित होता है। बिल्ट-इन रूपांतरणों को मारने का आपका एकमात्र मौका या तो है:

  1. आपने गणितीय सफलता को मारा जो इसके बारे में कुछ गंभीर कागजात लिखे जाने योग्य है।
  2. आप पर्याप्त मामलों को बाहर निकालते हैं जो आपके अपने उदाहरणों में नहीं होंगे कि जब अंतर्निहित बेहतर होते हैं तो आम तौर पर आपके अपने उपयोग के लिए अनुकूलित किया जाता है।

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

यदि आप उस बिंदु पर हैं जहां आपको आईईईई 754 कवर, या यहां तक ​​कि उनमें से एक बड़े पैमाने पर अनुपात को कवर करना है, तो आप चीजों को धीमा कर देंगे।

मैं या तो आपके पास जो कुछ भी है उसके साथ रहना चाहता हूं, उन मामलों को स्थानांतरित करना जहां double असुविधा के बावजूद लंबे समय तक चिपकने के लिए सुविधाजनक है, या decimal का उपयोग कर आवश्यक है।आप के साथ आसानी से एक long से एक decimal बना सकते हैं:

private static decimal DivideByBillion (long l) 
{ 
    if(l >= 0) 
    return new decimal((int)(l & 0xFFFFFFFF), (int)(uint)(l >> 32), 0, false, 9); 
    l = -l; 
    return new decimal((int)(l & 0xFFFFFFFF), (int)(uint)(l >> 32), 0, true, 9); 
} 

अब, decimal परिमाण धीमी है double (ठीक है क्योंकि यह एक दृष्टिकोण उद्घाटन प्रश्न में जो आपके जैसा लागू करता है की तुलना में गणित में उपयोग करने के लिए है, लेकिन एक अलग प्रतिपादक के साथ और बड़ा मंटिसा)। लेकिन अगर आपको स्ट्रिंग के लिए डिस्प्ले या प्रतिपादन के लिए मूल्य प्राप्त करने का एक सुविधाजनक तरीका चाहिए, तो decimal पर रूपांतरण को हाथ से हैक करने से double पर रूपांतरण को हाथ से हैकिंग करने के फायदे हैं, इसलिए देख सकता है।

+0

कोड में अभी भी प्रदर्शन बहुत महत्वपूर्ण है जहां युगल का उपयोग किया जाता है। यह सिर्फ इतना है कि वे उपयोगकर्ता प्लगइन्स हैं और उपयोगकर्ता उपयोगकर्ता फ़्लोटिंग पॉइंट नंबरों की अपेक्षा करते हैं। दशमलव का उपयोग निश्चित रूप से उपयोगकर्ताओं के लिए व्यावहारिक है लेकिन उनके साथ किए गए किसी भी काम के प्रदर्शन के लिए निराशाजनक है। चूंकि हमारा सभी इनपुट युगल से है (स्ट्रिंग या युगल रिकॉर्डिंग से बाइनरी के रूप में) तो मैं मंथिसा निकालने की सोच रहा हूं ... उसके साथ गणित कर रहा हूं ... फिर बस उत्पादन के लिए मंटिसा को बदल रहा है। उम्मीद है कि गोल और परिशुद्धता की कमी से बचें। – Wayne

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