2012-04-13 27 views
8

我有爲ARMv5TE構建的Qt 4.4.3。我嘗試轉換doubleQString錯誤的從Qt到QString的轉換在Qt上的ARM

#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 

如何獲取正確的琴絃?

回答

8

這看起來是一種永久性問題,但不是你的普通香草大端與小端問題。 ARM有時爲double使用不尋常的字節順序。從由Jean-米歇爾穆勒,等人:

...最接近 -7.0868766365730135 x 10^-268由字節 11 22 33 44 55 66 77 88的在存儲器中的序列編碼的雙精度數「手冊浮點運算的」 (從最低到最高 之一)在x86和Linux/IA-64平臺(他們說是 小端)和88 77 66 55 44 33 22 11在大多數的PowerPC平臺(他們說是大端 )。一些體系結構,如IA-64,ARM和PowerPC的 據說是雙端的。即它們可能是 是小端或大端,這取決於它們的 配置。

存在一個例外:一些基於ARM的平臺。 傳統上使用的浮點加速器(FPA) 結構中,其中的雙精度數在大端爲了根據 字節序的機器的分解成 兩個32位字並存儲ARM處理器,即一般的小端,意思是 上述數字由序列55 66 77 88 11 22 33 44編碼。 ARM最近推出了一種浮點運算的新體系結構 運算:矢量浮點運算(VFP),其中字以存儲在處理器的本地字節順序中。

當大端字節順序看,M_PI將有一個看起來表示這樣的:

0x400921fb54442d18 

通過8.6192e+97近似的大量預示了,看起來表示這樣的:

0x54442d18400921fb 

如果仔細觀察,兩個32位字是交換的,但32位字內的字節順序是相同的。顯然,ARM'傳統'雙點格式似乎令Qt庫(或Qt庫配置錯誤)混淆不清。

我不確定處理器是否使用傳統格式,而Qt預計它是VFP格式,或者事情是相反的。但它似乎是這兩種情況之一。

我也不確定如何解決問題 - 我猜想有一些選項可以構建Qt來正確處理這個問題。

下面的代碼片段將至少告訴你的編譯器使用的是什麼格式double,這可以幫助你縮小哪些需要在Qt的改變:

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(""); 

一個普通的小端機器會顯示:

11 22 33 44 55 66 77 88 

更新多一點分析:

目前,我無法對此進行任何真正的調試(我目前甚至無法訪問我的工作站),但通過查看http://qt.gitorious.org上的Qt源文件,可以進行附加分析:

它看起來像Qt調用qlocale.cpp中的QLocalePrivate::doubleToString()函數來將double轉換爲字母數字形式。

如果Qt編譯時定義了QT_QLOCALE_USES_FCVT,那麼QLocalePrivate::doubleToString()將使用該平臺的fcvt()函數來執行轉換。如果QT_QLOCALE_USES_FCVT而不是定義,那麼QLocalePrivate::doubleToString()結束呼叫_qdtoa()執行轉換。該函數直接檢查double的各個字段,並似乎假設double處於嚴格的大端或小端形式(例如,使用getWord0()getWord1()函數分別獲取double的低位和高位字)。

請參閱http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale.cpphttp://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale_tools.cpp或您自己的文件副本以獲取詳細信息。

假設你的平臺是採用傳統的ARM FPA表示爲double(其中double的32位半存儲在大端順序不管整個系統是否是小端的),我想你」需要定義QT_QLOCALE_USES_FCVT來構建Qt。我相信你所需要做的就是在構建Qt時將-DQT_QLOCALE_USES_FCVT選項傳遞給配置腳本。

+0

我已經添加了一些關於Qt內部似乎正在發生的事情以及我認爲是可能的解決方案。 – 2012-04-14 08:31:32

+0

很好研究。 +1 – 2012-04-16 08:11:24

+0

謝謝您的詳細回覆!其實問題是缺少選項「-DQT_QLOCALE_USES_FCVT」。重建後一切正常。在重建您的代碼片段之前,請打印以下行:'55 66 77 88 11 22 33 44'。 – 2012-04-16 09:41:38

4

相同的代碼在使用Qt 4.7.0的x86機器(運行Windows XP)上產生正確的輸出。

我看到下面的可能性問題的根源:

  • 編譯爲ARM

時也許是固定的Qt的新版本

  • 出事了一些bug我發現this forum post在一個類似的問題上,認爲它可能是一個大/小端轉換問題。

    我不知道如何解決這個問題,因爲我根本沒有使用過ARM,但也許這些信息可以幫助你。

  • +0

    這很可能是問題所在。Qt編譯爲錯誤的排序或某種效果。 – Mat 2012-04-13 15:44:42