I have Qt 4.4.3 built for ARMv5TE. I try to convert a double to 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;
}
but get strange output:
Pi is : 8.6192e+97
but pi is : "86191995128153827662389718947289094511677209256133209964237318700300913082475855805240843511529472.0000000000000000"
printf: 3.141593
How do I get the proper string?
This looks to be a sort of endianess issue, but not your plain-vanilla big-endian vs little-endian problem. ARM sometimes uses an unusual byte ordering for
double. From “Handbook of Floating-Point Arithmetic” by Jean-Michel Muller, et al.:When looked at in a big-endian byte order,
M_PIwill have a representation that looks like:The large number approximated by
8.6192e+97wil have a representation that looks like:If you look closely, the two 32-bit words are swapped, but the byte order within the 32-bit words is the same. So apparently, the ARM ‘traditional’ double point format seems to be confusing the Qt library (or the Qt library is misconfigured).
I’m not sure if the processor is using the traditional format and Qt expects it to be in VFP format, or if things are the other way around. But it seems to be one of those two situations.
I’m also not sure exactly how to fix the problem – I’d guess there’s some option for building Qt to handle this correctly.
the following snippet will at least tell you what format for
doublethe compiler is using, which may help you narrow down what needs to change in Qt:A plain little-endian machine will display:
Update with a bit more analysis:
At the moment, I’m unable to perform any real debugging of this (I don’t even have access to my workstation at the moment), but by looking at the Qt source available on http://qt.gitorious.org here’s additional analysis:
It looks like Qt calls in to the
QLocalePrivate::doubleToString()function in qlocale.cpp to convert adoubleto an alphanumeric form.If Qt is compiled with
QT_QLOCALE_USES_FCVTdefined, thenQLocalePrivate::doubleToString()will use the platform’sfcvt()function to perform the conversion. IfQT_QLOCALE_USES_FCVTis not defined, thenQLocalePrivate::doubleToString()ends up calling_qdtoa()to perform the conversion. That function examines the various fields of thedoubledirectly and appears to assume that thedoubleis in a strict big-endian or little-endian form (for example, using thegetWord0()andgetWord1()functions to get the low and high word of thedoublerespectively).See http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale.cpp and http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale_tools.cpp or your own copy of the files for details.
Assuming that your platform is using the traditional ARM FPA representation for
double(where the 32-bit halves of thedoubleare stored in big-endian order regardless of whether the overall system being little-endian), I think you’ll need to build Qt with theQT_QLOCALE_USES_FCVTdefined. I believe that all you’ll need to do is pass the-DQT_QLOCALE_USES_FCVToption to the configure script when building Qt.