8

我为 ARMv5TE 构建了 Qt 4.4.3。我尝试将 a 转换double为 a 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 等人的“浮点算术手册”:

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

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

当以大端字节顺序查看时,M_PI将具有如下所示的表示:

0x400921fb54442d18

由 wil 近似的大数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()qlocale.cpp 中的函数以将 a 转换double为字母数字形式。

如果 Qt 是用QT_QLOCALE_USES_FCVT定义的方式编译的,那么QLocalePrivate::doubleToString()将使用平台的fcvt()函数来执行转换。如果未定义,则QT_QLOCALE_USES_FCVT最终调用以执行转换。该函数直接检查 the 的各个字段,并且似乎假定 the是严格的大端或小端形式(例如,使用and函数分别获取 the 的低位和高位字)。QLocalePrivate::doubleToString()_qdtoa()doubledoublegetWord0()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(其中 32 位的一半以double大端顺序存储,无论整个系统是否为小端),我认为您需要构建 QtQT_QLOCALE_USES_FCVT定义的。我相信您需要做的就是-DQT_QLOCALE_USES_FCVT在构建 Qt 时将选项传递给配置脚本。

于 2012-04-13T23:10:02.093 回答
4

相同的代码在带有 Qt 4.7.0 的 x86 机器(运行 Windows XP)上产生正确的输出。

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

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

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

我不知道如何解决这个问题,因为我根本没有使用 ARM 的经验,但也许这些信息对你有帮助。

于 2012-04-13T14:54:18.887 回答