2012-04-13 13 views
8

पर क्यूटी में डबल से क्यूस्ट्रिंग से गलत रूपांतरण मेरे पास ARMv5TE के लिए QT 4.4.3 बनाया गया है।एआरएम

#include <QtCore/QtCore> 
#include <cmath> 

int main(int argc, char** argv) 
{ 
    const double pi = M_PI; 
    qDebug() << "Pi is : " << pi << "\n but pi is : " << QString::number(pi, 'f', 6); 
    printf("printf: %f\n",pi); 

    return 0; 
} 

लेकिन अजीब आउटपुट प्राप्त:

Pi is : 8.6192e+97 
but pi is : "86191995128153827662389718947289094511677209256133209964237318700300913082475855805240843511529472.0000000000000000" 
printf: 3.141593 

मैं उचित स्ट्रिंग कैसे मिलता है मैं एक एक QString को double बदलने की कोशिश?

उत्तर

8

यह एक प्रकार का अंतहीन मुद्दा दिखता है, लेकिन आपकी सादा-वेनिला बड़ी-एंडियन बनाम छोटी-छोटी समस्या नहीं है। एआरएम कभी-कभी double के लिए असामान्य बाइट ऑर्डरिंग का उपयोग करता है। से जीन मिशेल मुलर, एट अल .:

... कि -7.0868766365730135 x 10^-268 के सबसे करीब है स्मृति में बाइट्स 11 22 33 44 55 66 77 88 के अनुक्रम द्वारा इनकोडिंग डबल परिशुद्धता संख्या से "हैंडबुक फ्लोटिंग प्वाइंट अंकगणित की" 86 पर और लिनक्स/IA-64 प्लेटफॉर्म (सबसे कम से उच्चतम एक करने के लिए) (वे होने के लिए कहा जाता है थोड़ा-endian) और सबसे PowerPC प्लेटफार्मों पर 88 77 66 55 44 33 22 11 (द्वारा वे होने के लिए कहा जाता है बड़े endian)। कुछ आर्किटेक्चर, जैसे आईए -64, एआरएम, और पावरपीसी के रूप में द्वि-एंडियन कहा जाता है। यानी, वे अपने कॉन्फ़िगरेशन के आधार पर या तो छोटे-एंडियन या बड़े-एंडियन हो सकते हैं।

कुछ अपवाद मौजूद है: कुछ एआरएम-आधारित प्लेटफ़ॉर्म। एआरएम प्रोसेसर पारंपरिक रूप से फ्लोटिंग प्वाइंट त्वरक (FPA) वास्तुकला, जहां डबल परिशुद्धता संख्या मशीन के endianess के अनुसार बड़े endian क्रम में दो 32-बिट शब्द में विघटित और जमा हो जाती है का इस्तेमाल किया है , यानी, सामान्य रूप से थोड़ा-अंतराल, जिसका अर्थ है कि उपर्युक्त संख्या अनुक्रम 55 66 77 88 11 22 33 44 द्वारा एन्कोड किया गया है। एआरएम ने हाल ही में फ्लोटिंग-पॉइंट अंकगणितीय के लिए एक नया आर्किटेक्चर पेश किया है: वेक्टर फ़्लोटिंग-पॉइंट (वीएफपी), जहां प्रोसेसर के देशी बाइट ऑर्डर में शब्द संग्रहीत किए जाते हैं।

जब एक बड़े endian बाइट क्रम में देखा, M_PI एक प्रतिनिधित्व है कि लग रहा है की तरह होगा:

0x400921fb54442d18 

बड़े 8.6192e+97 इसका अनुमान संख्या wil एक प्रतिनिधित्व है कि लग रहा है जैसे:

0x54442d18400921fb 

यदि आप बारीकी से देखते हैं, तो दो 32-बिट शब्द स्वैप किए जाते हैं, लेकिन 32-बिट शब्दों के भीतर बाइट ऑर्डर समान होता है। तो जाहिर है, एआरएम 'पारंपरिक' डबल प्वाइंट प्रारूप क्यूटी लाइब्रेरी को भ्रमित कर रहा है (या क्यूटी लाइब्रेरी गलत कॉन्फ़िगर किया गया है)।

मुझे यकीन नहीं है कि प्रोसेसर पारंपरिक प्रारूप का उपयोग कर रहा है और क्यूटी उम्मीद करता है कि यह वीएफपी प्रारूप में हो, या यदि चीजें दूसरी तरफ हैं। लेकिन ऐसा लगता है कि उन दो स्थितियों में से एक है।

मुझे यह भी सुनिश्चित नहीं है कि समस्या को ठीक कैसे किया जाए - मुझे लगता है कि क्यूटी को सही ढंग से संभालने के लिए कुछ विकल्प है।

निम्नलिखित स्निपेट में कम से कम आप double के लिए क्या प्रारूप संकलक उपयोग कर रहा है बता देंगे, जो आप को सीमित करने में क्या क्यूटी में बदलने की जरूरत में मदद कर सकते हैं:

unsigned char* b; 
unsigned char* e; 

double x = -7.0868766365730135e-268; 

b = (unsigned char*) &x; 
e = b + sizeof(x); 

for (; b != e; ++b) { 
    printf("%02x ", *b); 
} 

    puts(""); 

एक सादे थोड़ा-endian मशीन प्रदर्शित होगा: थोड़ा और विश्लेषण के साथ

11 22 33 44 55 66 77 88 

अद्यतन:

फिलहाल, मैं इस के किसी भी वास्तविक डिबगिंग को करने में असमर्थ हूं (मुझे इस समय मेरे वर्कस्टेशन तक पहुंच भी नहीं है), लेकिन http://qt.gitorious.org पर उपलब्ध क्यूटी स्रोत को देखकर यहां अतिरिक्त विश्लेषण:

यह double को अल्फान्यूमेरिक रूप में परिवर्तित करने के लिए qlocale.cpp में QLocalePrivate::doubleToString() फ़ंक्शन में क्यूटी कॉल करता है।

क्यूटी QT_QLOCALE_USES_FCVT परिभाषित के साथ संकलित किया गया है, तो QLocalePrivate::doubleToString() रूपांतरण करने के लिए मंच के fcvt() समारोह का प्रयोग करेंगे। यदि QT_QLOCALE_USES_FCVT परिभाषित नहीं है, तो QLocalePrivate::doubleToString() रूपांतरण करने के लिए _qdtoa() पर कॉल करना समाप्त होता है। यही कारण है कि समारोह double सीधे के विभिन्न क्षेत्रों की जांच करता है और getWord0() और getWord1() कार्यों का उपयोग कर क्रमशः double के निम्न और उच्च शब्द पाने के लिए माना कि double (उदाहरण के लिए एक सख्त बड़े endian या थोड़ा-endian रूप में है प्रकट होता है,)।

http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale.cpp और http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale_tools.cpp या विवरण के लिए फ़ाइलों की अपनी प्रति देखें।

यह मानते हुए कि अपने मंच double (जहां double के 32-बिट हिस्सों चाहे समग्र प्रणाली थोड़ा-endian जा रहा है की परवाह किए बिना बड़े endian क्रम में जमा हो जाती है) के लिए पारंपरिक एआरएम FPA प्रतिनिधित्व उपयोग कर रहा है, मैं आपको लगता है ' QT_QLOCALE_USES_FCVT परिभाषित के साथ क्यूटी बनाने की आवश्यकता होगी। मेरा मानना ​​है कि क्यूटी बनाने के दौरान आपको कॉन्फ़िगर स्क्रिप्ट के -DQT_QLOCALE_USES_FCVT विकल्प को पास करने की आवश्यकता होगी।

+0

मैंने क्यूटी के अंदर क्या प्रतीत होता है, इसके बारे में कुछ और जोड़ा है जो मुझे लगता है कि एक संभावित समाधान है। –

+0

अच्छी तरह से शोध किया। +1 –

+0

विस्तृत प्रतिक्रिया के लिए धन्यवाद! दरअसल समस्या '-QQT_QLOCALE_USES_FCVT' विकल्पों की कमी थी। सब कुछ पुनर्निर्माण के बाद सही ढंग से काम किया। अपने स्निपेट को पुनर्निर्माण करने से पहले निम्नलिखित पंक्ति मुद्रित करें: '55 66 77 88 11 22 33 44'। –

4

वही कोड क्यूटी 4.7.0 के साथ एक x86 मशीन (विंडोज एक्सपी चल रहा है) पर उचित आउटपुट उत्पन्न करता है।

मैं समस्या के स्रोत के लिए निम्नलिखित संभावनाओं को देखने:

  • कुछ बग जो शायद
  • कुछ गलत हो गया क्यूटी के एक नए संस्करण में तय हो गई है जब एआरएम

के लिए संकलन मुझे एक ही समस्या पर this forum post मिला जो मानता है कि यह एक बड़ी/छोटी-एंडियन रूपांतरण समस्या हो सकती है।

मैं यह नहीं कह सकता कि इसे कैसे ठीक किया जाए क्योंकि मुझे एआरएम के साथ अनुभव नहीं हुआ है, लेकिन शायद यह जानकारी आपको वैसे भी मदद करेगी।

+0

यह सबसे अधिक संभावना है।Qt गलत endianness या उस प्रभाव के लिए कुछ के लिए संकलित। – Mat

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