2010-08-30 8 views
6

मैं एक प्रोग्राम लिख रहा हूं जो आईसीसी रंग प्रारूप बनाता है। ये प्रारूप s15Fixed16Number नामक डेटा प्रकार निर्दिष्ट करते हैं जिसमें एक साइन बिट, 15 पूर्णांक बिट्स और 16 आंशिक बिट्स होते हैं। आईईईई 754 32-बिट फ्लोट्स में साइन बिट, 8 एक्सपोनेंट बिट्स और 23 आंशिक बिट्स हैं।एक फ्लोट को गैर मानक एन्कोडिंग में परिवर्तित करने के लिए कैसे करें

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

मैं कोको का उपयोग कर रहा हूं लेकिन मुझे लगता है कि यह महत्वपूर्ण नहीं है; किसी भी सी समारोह काम करना चाहिए। यहाँ s15Fixed16Number प्रारूप में मौजूद कुछ उदाहरण मान हैं:

   -32768.0 = 0x80000000 
        0 = 0x00000000 
        1.0 = 0x00010000 
32767 + (65535/65536) = 0x7FFFFFFF 

मुझे लगता है कि यह कुछ समय है कि संख्यात्मक अभिकलन वर्ग बाद से किया गया है!

+0

यदि उदाहरण रूपांतरण सही हैं, तो s15Fixed16Number में साइन बिट नहीं है: - यह केवल एक मानक twos 'पूरक हस्ताक्षरित एन्कोडिंग है। जैसे -32768.0 = 0x80000000 का तात्पर्य है कि: -1.0 = 0xffff0000 –

+0

यह आईसीसी प्रोफाइल प्रारूप विशिष्टता का समर्थन करता है जो s15Fixed16Number का दावा करता है: "यह प्रकार एक निश्चित हस्ताक्षरित 4 बाइट/32 बिट मात्रा का प्रतिनिधित्व करता है जिसमें 16 fractional बिट्स हैं।" यह नहीं कहता कि इसमें एक संकेत बिट है, लेकिन यह संख्या हस्ताक्षरित है। –

+0

मानक s15Fix16Number, मान -32768.9 999 के रूप में एन्कोड किए गए ऋणात्मक संख्या का केवल एक (बोगस) उदाहरण देता है। यह मान्य सीमा के बाहर काफी स्पष्ट रूप से है। यह स्पष्ट नहीं है कि -1 को कोड किया जाना चाहिए; यह स्पष्ट नहीं है कि न्यूनतम मान्य एन्कोडेड मान क्या है (-32768.00000 या -32767.9 99 99)। परिशिष्ट में हेडर में उपयोग किया जाने वाला प्रकार यह है: 'टाइपपीफ लांग आईसीएस 15 फ़िक्स्ड 16 नम्बर;'। –

उत्तर

2

मानते हैं कि आपके सी पर्यावरण 2 के पूरक पूर्णांक करता है, तो यह ऐसा लगता है जितना आसान है।

typedef long s1516; // 32bit 2's complement signed integer 
s1516 floattos1516(double f) { 
    return (s1516)(f * 65536. + 0.5); 
} 

प्रतिनिधित्व 16 बिट्स अंश के साथ एक निश्चित बिंदु मान है। यह एक तर्कसंगत संख्या के समान है जिसका denominator हमेशा 65536 (या 2) है। एक फ्लोटिंग पॉइंट वैल्यू से इस तरह के तर्कसंगत बनाने के लिए, आप केवल denominator द्वारा गुणा करें। फिर यह सिर्फ एक उचित दौर की बात है, और अभिन्न प्रकार के लिए एक छिद्र है।

मानक ने उनके द्वारा किए गए फॉर्म को चुना क्योंकि यह केवल तब काम करता है जब आपका सिस्टम 2 के पूरक पूर्णांक अंकगणित का उपयोग करता है। हालांकि यह सच है कि बाएं सबसे बिट संकेत का प्रतिनिधित्व करता है, यह उस अर्थ में एक संकेत बिट नहीं है जिसका उपयोग फ्लोटिंग पॉइंट प्रस्तुति में किया जाता है।

तो अपनी गणना सही मायने में हैं float बल्कि double से, तो आप पाएंगे कि आप अपनी गणना में के रूप में ज्यादा सटीक रूप में पूर्ण पैमाने के पास संख्या के लिए नियत बिन्दु मूल्य में उपलब्ध है नहीं है। यदि आप double में गणना करते हैं, तो परिणाम के मुकाबले आपकी गणना में हमेशा अधिक सटीकता होगी।

संपादित करें:

जाहिरा तौर पर नवीनतम कल्पना उपलब्ध है from the ICC रूप विशिष्टता ICC.1: 2004-10 (प्रोफ़ाइल संस्करण 4.2.0.0)। धारा 5.1.3:

5.1.3 s15Fixed16Number

एक निश्चित पर हस्ताक्षर किए 4 बाइट/32-बिट मात्रा जो 16 आंशिक बिट्स के रूप में तालिका 3 में दिखाया गया है।

 
Table 3 — s15Fixed16Number 
    Number    Encoding 
-32768,0    80000000h 
    0     00000000h 
    1,0    00010000h 
32767 + (65535/65536) 7FFFFFFFh 

एक दशमलव बिंदु के प्रतिनिधित्व के लिए स्थानीय वरीयता के अलावा, इन मूल्यों मेरी समझ के साथ पूरी तरह से संगत है कि प्रतिनिधित्व बस हस्ताक्षरित किया गया है 2 के पूरक पूर्णांकों कि 65536 से विभाजित किया जाना चाहिए उनके मूल्यों मिल रहे हैं।

प्रतिनिधित्व के लिए प्राकृतिक रूपांतरण केवल 65536 से गुणा करना है, और इससे बस विभाजित करना है। उपयुक्त गोलाकार नियम चुनना वरीयता का मामला है।

पूर्ण पैमाने की रेंज -32768.0 (0x80000000) से लगभग 32767.9999847412 (0x7fffffff) तक है।

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

+0

आपके कोड में मेरे परीक्षण ढांचे (आउटपुट में एक अतिरिक्त कॉलम के रूप में) प्लग इन होने पर रेंज समस्याओं को स्पॉट करने के लिए त्रुटि जांच की कमी है। साथ ही, जब इनपुट नकारात्मक होता है तो परिणाम गलत होता है (-1.0 के लिए 0xFFFF0001 दे रहा है)। +0.5 के साथ गोलाकार मेरे उत्तरों से मामूली विचलन का कारण बनता है, लेकिन इसके कारण आपका मेरा बेहतर हो सकता है। –

+0

-1.0 बिल्कुल 0xFFFF0000 होगा जो एन्कोडिंग मानता है जिसे मैं समझता हूं। हालांकि, गोल करना शायद सबसे अच्छा जवाब नहीं हो सकता है। मुझे इस विशेष टुकड़े को अवांछित के रूप में चिह्नित करना चाहिए, लेकिन मैं नियमित रूप से फ़्लोटिंग पॉइंट से निश्चित बिंदु तक कनवर्ट करने के लिए टुकड़ों का उपयोग करता हूं। – RBerteig

+0

@ जोनाथन, मुझे लगता है कि आप कल्पना सोचने पर विचार कर रहे हैं। जैसा कि मैंने इसे पढ़ा है, इसमें केवल सरल और प्राकृतिक अर्थ हो सकता है, और उद्धृत नमूना मान सुसंगत हैं। – RBerteig

2

फ्लोट के आंतरिक प्रतिनिधित्व के बारे में न लें। स्थिर-बिंदु मान स्थिरांक कारक के साथ केवल पूर्णांक होते हैं। बस याद रखें कि आपके लक्षित प्रारूप की तुलना में आपके पास फ्लोट्स में अधिक सीमित सटीकता है, इसलिए बड़े मूल्यों के लिए निचले 9 बिट्स में अपेक्षित मान बंद हो सकते हैं।

//s15Fixed16Number is presumably typedef'ed to unsigned int 
float foo = 1.0f; 
int fooFixedSigned = (int)(foo * 65536); 
s15Fixed16Number fooFixed = (s15Fixed16Number)(abs(fooFixedSigned)); 
if (foo < 0) fooFixed = fooFixed | (1 << 31); 
//you'll also need to explicitly check for overflows and underflows and handle them however is appropriate to your situation 

संपादित करें: ठीक किया & लिए |

+0

जैसा कि एलन ने दिखाया है, निश्चित बिंदु मानों को यूनिट मान द्वारा गुणा करके या विभाजित करके फ़्लोटिंग पॉइंट मानों में और से परिवर्तित किया जा सकता है। यह प्रारूप एक साइन बिट निर्दिष्ट करके एक छोटा मोड़ फेंकता है। –

+0

आपको 'int' की बजाय' long' का उपयोग करना चाहिए - पूर्व में कम से कम 32 बिट्स हैं, जबकि बाद में केवल 16 की गारंटी है। – caf

+0

क्षमा करें, नहीं। बंद करो, लेकिन नहीं। प्रतिनिधित्व स्पष्ट रूप से कहता है कि यह 2 पूरक है। आपको पूर्ण मूल्य प्राप्त करके यह नहीं मिलता है। इसके अलावा, साइन बिट सेट करने के लिए बिट-वार और ऑपरेटर का उपयोग करने का आपका प्रयास * बिट * को छोड़कर * हर बिट को साफ़ करेगा। – RBerteig

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

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