8

ARMv5TE用にビルドされたQt 4.4.3があります。a を a に変換しようとしdoubleましたQString:

#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

適切な文字列を取得するにはどうすればよいですか?

4

2 に答える 2

8

これは一種のエンディアンの問題のように見えますが、単純なバニラのビッグエンディアンとリトルエンディアンの問題ではありません。ARM は、double. Jean-Michel Muller ほかによる「Handbook of Floating-Point Arithmetic」より:

... に最も近い倍精度数は 、x86 および Linux/IA-64 プラットフォーム (リトル エンディアンと呼ばれる)では、メモリ内のバイト シーケンス (最小から最大) -7.0868766365730135 x 10^-268によってエンコードされます 。ほとんどのPowerPC プラットフォームで (ビッグエンディアンと言われています)。IA-64、ARM、PowerPC などの一部のアーキテクチャは、バイエンディアンと言われています。つまり、構成に応じて、リトル エンディアンまたはビッグ エンディアンのいずれかになります。11 22 33 44 55 66 77 8888 77 66 55 44 33 22 11

例外があります: 一部の ARM ベースのプラットフォームです。ARM プロセッサは従来、浮動小数点アクセラレータ(FPA) アーキテクチャを使用してきました。このアーキテクチャでは、倍精度数がビッグ エンディアンの順序で 2 つの 32 ビット ワードに分解され、マシンのエンディアン (リトルエンディアン) に従って格納されます。一般に、これは上記の数値がシーケンスによってエンコードされることを意味します55 66 77 88 11 22 33 44。ARM は最近、浮動小数点演算用の新しいアーキテクチャであるベクトル浮動小数点(VFP) を導入しました。このアーキテクチャでは、ワードはプロセッサのネイティブ バイト オーダーで格納されます。

ビッグ エンディアンのバイト順でM_PI見ると、次のような表現になります。

0x400921fb54442d18

wilによって近似された大きな数8.6192e+97は、次のように表現されます。

0x54442d18400921fb

よく見ると、2 つの 32 ビット ワードが入れ替わっていますが、32 ビット ワード内のバイト順は同じです。どうやら、ARM の「伝統的な」ダブルポイント形式は Qt ライブラリを混乱させているようです (または Qt ライブラリの設定が間違っています)。

プロセッサが従来の形式を使用しており、Qt が VFP 形式であることを期待しているのか、それとも逆なのかはわかりません。しかし、それはこれら2つの状況のいずれかのようです。

また、問題を修正する方法も正確にはわかりません.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 がQLocalePrivate::doubleToString()qlocale.cpp の関数を呼び出して adoubleを英数字形式に変換しているようです。

Qt がQT_QLOCALE_USES_FCVT定義済みでコンパイルされているQLocalePrivate::doubleToString()場合、プラットフォームのfcvt()関数を使用して変換を実行します。が定義されていない場合QT_QLOCALE_USES_FCVTは、変換を実行するために呼び出されます。この関数は のさまざまなフィールドを直接調べ、が厳密なビッグ エンディアンまたはリトル エンディアン形式であると想定しているように見えます (たとえば、関数と関数を使用してそれぞれの下位ワードと上位ワードを取得します)。QLocalePrivate::doubleToString()_qdtoa()doubledoublegetWord0()getWord1()double

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プラットフォームが従来の ARM FPA 表現(システム全体がリトル エンディアンであるかどうかに関係なく、32 ビットの半分がビッグ エンディアンの順序で格納される) を使用していると仮定すると、doubleQt をビルドする必要があると思います。QT_QLOCALE_USES_FCVT定義されています。-DQT_QLOCALE_USES_FCVTQt をビルドするときに configure スクリプトにオプションを渡すだけでよいと思います。

于 2012-04-13T23:10:02.093 に答える
4

同じコードで、Qt 4.7.0を搭載したx86マシン(Windows XPを実行)で適切な出力が生成されます。

問題の原因について、次の可能性があります。

  • Qtの新しいバージョンで修正される可能性のあるいくつかのバグ
  • ARM用にコンパイルするときに問題が発生しました

ビッグ/リトルエンディアンの変換の問題である可能性があると思われる同様の問題に関するこのフォーラムの投稿を見つけました。

ARMの経験がまったくないため、これを修正する方法がわかりませんが、この情報がとにかく役立つかもしれません。

于 2012-04-13T14:54:18.887 に答える