繁体   English   中英

ARM上Qt中从double到QString的错误转换

[英]Wrong conversion from double to QString in Qt on ARM

我有为ARMv5TE构建的Qt 4.4.3。 我尝试将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

我如何获得正确的字符串?

这看起来像是一种endianess问题,但不是普通的big-endian和little-endian问题。 ARM有时会使用异常的字节顺序进行double 来自Jean-Michel Muller等人的“浮点运算手册”:

...最接近-7.0868766365730135 x 10^-268的双精度数字由x86和Linux /上的内存字节序列11 22 33 44 55 66 77 88编码(从最低到最高) IA-64平台(据说它们是小端 )和88 77 66 55 44 33 22 11在大多数PowerPC平台上(据说它们都是大端 )。 一些架构,例如IA-64,ARM和PowerPC,据说是双端的 即,根据其配置,它们可能是小端或大端。

存在一个例外:一些基于ARM的平台。 ARM处理器传统上使用浮点加速器 (FPA)架构,其中双精度数字按大端顺序分解为两个32位字,并根据机器的字节顺序存储,即little-endian通常,这意味着上述数字由序列55 66 77 88 11 22 33 44编码。 ARM最近推出了一种新的浮点运算架构: 向量浮点 (VFP),其中的单词以处理器的本机字节顺序存储。

当以big-endian字节顺序M_PI时, 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调用QLocalePrivate::doubleToString()中的QLocalePrivate::doubleToString()函数将double转换为字母数字形式。

如果Qt是在定义了QT_QLOCALE_USES_FCVT情况下编译的,那么QLocalePrivate::doubleToString()将使用平台的fcvt()函数来执行转换。 如果QT_QLOCALE_USES_FCVT 没有定义,则QLocalePrivate::doubleToString()结束调用_qdtoa()来执行转换。 该函数直接检查double的各个字段,并假设double是严格的big-endian或little-endian形式(例如,使用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 (无论整个系统是否为little-endian, double端的32位半部都以big-endian顺序存储),我认为你需要构建Qt定义了QT_QLOCALE_USES_FCVT 我相信你需要做的就是在构建Qt时将-DQT_QLOCALE_USES_FCVT选项传递给configure脚本。

相同的代码在Qt 4.7.0的x86机器(运行Windows XP)上产生适当的输出。

我看到了问题根源的以下可能性:

  • 可能在较新版本的Qt中修复了一些错误
  • 编译ARM时出错了

我发现这个论坛帖子上有一个类似的问题,假设它可能是一个大/小端转换问题。

我无法告诉如何解决这个问题,因为我根本没有使用过ARM,但这些信息可能对你有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM