Interpret precision == -128 as "shortest" double conversion

Also use this for converting doubles with QVariant. We generally want
exact results there, rather than adding rounding errors whenever we
convert.

[ChangeLog][QtCore][QLocale] Added special value for double conversion
precision to get shortest accurate representation.

Change-Id: I905b8a103f39adf31d24b6ce2c8a283cf271b597
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
This commit is contained in:
Ulf Hermann 2015-10-16 16:52:51 +02:00
parent 04695c7a91
commit 726fed0d67
10 changed files with 171 additions and 65 deletions

View File

@ -56,6 +56,7 @@
#include "qbytearraylist.h"
#endif
#include "private/qvariant_p.h"
#include "private/qlocale_p.h"
#include "qmetatype_p.h"
#include <qmetaobject.h>
@ -71,18 +72,6 @@
QT_BEGIN_NAMESPACE
#ifndef DBL_MANT_DIG
# define DBL_MANT_DIG 53
#endif
#ifndef FLT_MANT_DIG
# define FLT_MANT_DIG 24
#endif
const int log10_2_10000 = 30103; // log10(2) * 100000
// same as C++11 std::numeric_limits<T>::max_digits10
const int max_digits10_double = (DBL_MANT_DIG * log10_2_10000) / 100000 + 2;
const int max_digits10_float = (FLT_MANT_DIG * log10_2_10000) / 100000 + 2;
namespace {
class HandlersManager
{
@ -433,10 +422,10 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*str = QString::number(qMetaTypeUNumber(d));
break;
case QMetaType::Float:
*str = QString::number(d->data.f, 'g', max_digits10_float);
*str = QString::number(d->data.f, 'g', QLocale::FloatingPointShortest);
break;
case QVariant::Double:
*str = QString::number(d->data.d, 'g', max_digits10_double);
*str = QString::number(d->data.d, 'g', QLocale::FloatingPointShortest);
break;
#if !defined(QT_NO_DATESTRING)
case QVariant::Date:
@ -625,10 +614,10 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*ba = v_cast<QString>(d)->toUtf8();
break;
case QVariant::Double:
*ba = QByteArray::number(d->data.d, 'g', max_digits10_double);
*ba = QByteArray::number(d->data.d, 'g', QLocale::FloatingPointShortest);
break;
case QMetaType::Float:
*ba = QByteArray::number(d->data.f, 'g', max_digits10_float);
*ba = QByteArray::number(d->data.f, 'g', QLocale::FloatingPointShortest);
break;
case QMetaType::Char:
case QMetaType::SChar:

View File

@ -2743,7 +2743,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
const QChar exponential, const QChar group, const QChar decimal,
double d, int precision, DoubleForm form, int width, unsigned flags)
{
if (precision < 0)
if (precision != QLocale::FloatingPointShortest && precision < 0)
precision = 6;
if (width < 0)
width = 0;
@ -2753,7 +2753,9 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
int decpt;
int bufSize = 1;
if (form == DFDecimal) // optimize for numbers smaller than 512k
if (precision == QLocale::FloatingPointShortest)
bufSize += DoubleMaxSignificant;
else if (form == DFDecimal) // optimize for numbers between -512k and 512k
bufSize += ((d > (1 << 19) || d < -(1 << 19)) ? DoubleMaxDigitsBeforeDecimal : 6) +
precision;
else // Add extra digit due to different interpretations of precision. Also, "nan" has to fit.
@ -2798,7 +2800,20 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
PrecisionMode mode = (flags & Alternate) ?
PMSignificantDigits : PMChopTrailingZeros;
if (decpt != digits.length() && (decpt <= -4 || decpt > precision))
int cutoff = precision < 0 ? 6 : precision;
// Find out which representation is shorter
if (precision == QLocale::FloatingPointShortest && decpt > 0) {
cutoff = digits.length() + 4; // 'e', '+'/'-', one digit exponent
if (decpt <= 10) {
++cutoff;
} else {
cutoff += decpt > 100 ? 2 : 1;
}
if (!always_show_decpt && digits.length() > decpt)
++cutoff; // decpt shown in exponent form, but not in decimal form
}
if (decpt != digits.length() && (decpt <= -4 || decpt > cutoff))
num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
digits, decpt, precision, mode,
always_show_decpt);

View File

@ -848,6 +848,10 @@ public:
};
Q_DECLARE_FLAGS(NumberOptions, NumberOption)
enum FloatingPointPrecisionOption {
FloatingPointShortest = -128
};
enum CurrencySymbolFormat {
CurrencyIsoCode,
CurrencySymbol,

View File

@ -940,6 +940,23 @@
\sa setNumberOptions(), numberOptions()
*/
/*!
\enum QLocale::FloatingPointPrecisionOption
This enum defines constants that can be given as precision to QString::number(),
QByteArray::number(), and QLocale::toString() when converting floats or doubles,
in order to express a variable number of digits as precision.
\value FloatingPointShortest The conversion algorithm will try to find the
shortest accurate representation for the given number. "Accurate" means
that you get the exact same number back from an inverse conversion on
the generated string representation.
\sa toString(), QString, QByteArray
\since 5.7
*/
/*!
\enum QLocale::MeasurementSystem

View File

@ -114,10 +114,16 @@ void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *
if (form == QLocaleData::DFExponent && precision >= 0)
++precision;
double_conversion::DoubleToStringConverter::DoubleToAscii(d,
form == QLocaleData::DFDecimal ? double_conversion::DoubleToStringConverter::FIXED :
double_conversion::DoubleToStringConverter::PRECISION,
precision, buf, bufSize, &sign, &length, &decpt);
double_conversion::DoubleToStringConverter::DtoaMode mode;
if (precision == QLocale::FloatingPointShortest) {
mode = double_conversion::DoubleToStringConverter::SHORTEST;
} else if (form == QLocaleData::DFSignificantDigits || form == QLocaleData::DFExponent) {
mode = double_conversion::DoubleToStringConverter::PRECISION;
} else {
mode = double_conversion::DoubleToStringConverter::FIXED;
}
double_conversion::DoubleToStringConverter::DoubleToAscii(d, mode, precision, buf, bufSize,
&sign, &length, &decpt);
#else // QT_NO_DOUBLECONVERSION || QT_BOOTSTRAPPED
// Cut the precision at 999, to fit it into the format string. We can't get more than 17
@ -126,6 +132,8 @@ void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *
// to honor higher precisions. We define that at more than 999 digits that is not the case.
if (precision > 999)
precision = 999;
else if (precision == QLocale::FloatingPointShortest)
precision = QLocaleData::DoubleMaxSignificant; // "shortest" mode not supported by snprintf
if (isZero(d)) {
// Negative zero is expected as simple "0", not "-0". We cannot do d < 0, though.
@ -442,7 +450,7 @@ QString qlltoa(qlonglong l, int base, const QChar zero)
}
QString &decimalForm(QChar zero, QChar decimal, QChar group,
QString &digits, int decpt, uint precision,
QString &digits, int decpt, int precision,
PrecisionMode pm,
bool always_show_decpt,
bool thousands_group)
@ -459,11 +467,11 @@ QString &decimalForm(QChar zero, QChar decimal, QChar group,
if (pm == PMDecimalDigits) {
uint decimal_digits = digits.length() - decpt;
for (uint i = decimal_digits; i < precision; ++i)
for (int i = decimal_digits; i < precision; ++i)
digits.append(zero);
}
else if (pm == PMSignificantDigits) {
for (uint i = digits.length(); i < precision; ++i)
for (int i = digits.length(); i < precision; ++i)
digits.append(zero);
}
else { // pm == PMChopTrailingZeros
@ -485,18 +493,18 @@ QString &decimalForm(QChar zero, QChar decimal, QChar group,
QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
QChar group, QChar plus, QChar minus,
QString &digits, int decpt, uint precision,
QString &digits, int decpt, int precision,
PrecisionMode pm,
bool always_show_decpt)
{
int exp = decpt - 1;
if (pm == PMDecimalDigits) {
for (uint i = digits.length(); i < precision + 1; ++i)
for (int i = digits.length(); i < precision + 1; ++i)
digits.append(zero);
}
else if (pm == PMSignificantDigits) {
for (uint i = digits.length(); i < precision; ++i)
for (int i = digits.length(); i < precision; ++i)
digits.append(zero);
}
else { // pm == PMChopTrailingZeros
@ -534,7 +542,7 @@ QString qdtoa(qreal d, int *decpt, int *sign)
// Some versions of libdouble-conversion like an extra digit, probably for '\0'
char result[QLocaleData::DoubleMaxSignificant + 1];
doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocaleData::DoubleMaxSignificant, result,
doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest, result,
QLocaleData::DoubleMaxSignificant + 1, nonNullSign, length, nonNullDecpt);
// Skip trailing zeroes. The DoubleMaxSignificant precision is the worst case.

View File

@ -81,13 +81,13 @@ enum PrecisionMode {
};
QString &decimalForm(QChar zero, QChar decimal, QChar group,
QString &digits, int decpt, uint precision,
QString &digits, int decpt, int precision,
PrecisionMode pm,
bool always_show_decpt,
bool thousands_group);
QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
QChar group, QChar plus, QChar minus,
QString &digits, int decpt, uint precision,
QString &digits, int decpt, int precision,
PrecisionMode pm,
bool always_show_decpt);

View File

@ -1,8 +1,11 @@
CONFIG += testcase
TARGET = tst_qvariant
QT = core testlib
QT = core-private testlib
INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qvariant.cpp
RESOURCES += qvariant.qrc
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
contains(QT_CONFIG, c++11): CONFIG += c++11
!contains(QT_CONFIG, doubleconversion):!contains(QT_CONFIG, system-doubleconversion) {
DEFINES += QT_NO_DOUBLECONVERSION
}

View File

@ -56,6 +56,7 @@
#include <QBuffer>
#include "qnumeric.h"
#include <private/qlocale_p.h>
#include "tst_qvariant_common.h"
class CustomNonQObject;
@ -1028,7 +1029,11 @@ void tst_QVariant::toByteArray_data()
QTest::newRow( "int" ) << QVariant( -123 ) << QByteArray( "-123" );
QTest::newRow( "uint" ) << QVariant( (uint)123 ) << QByteArray( "123" );
QTest::newRow( "double" ) << QVariant( 123.456 ) << QByteArray( "123.456" );
QTest::newRow( "float" ) << QVariant( 123.456f ) << QByteArray( "123.456001" );
// Conversion from float to double adds bits of which the double-to-string converter doesn't
// know they're insignificant
QTest::newRow( "float" ) << QVariant( 123.456f ) << QByteArray( "123.45600128173828" );
QTest::newRow( "longlong" ) << QVariant( (qlonglong)34 ) << QByteArray( "34" );
QTest::newRow( "ulonglong" ) << QVariant( (qulonglong)34 ) << QByteArray( "34" );
}
@ -1054,7 +1059,11 @@ void tst_QVariant::toString_data()
QTest::newRow( "int" ) << QVariant( -123 ) << QString( "-123" );
QTest::newRow( "uint" ) << QVariant( (uint)123 ) << QString( "123" );
QTest::newRow( "double" ) << QVariant( 123.456 ) << QString( "123.456" );
QTest::newRow( "float" ) << QVariant( 123.456f ) << QString( "123.456001" );
// Conversion from float to double adds bits of which the double-to-string converter doesn't
// know they're insignificant
QTest::newRow( "float" ) << QVariant( 123.456f ) << QString( "123.45600128173828" );
QTest::newRow( "bool" ) << QVariant( true ) << QString( "true" );
QTest::newRow( "qdate" ) << QVariant( QDate( 2002, 1, 1 ) ) << QString( "2002-01-01" );
QTest::newRow( "qtime" ) << QVariant( QTime( 12, 34, 56 ) ) << QString( "12:34:56" );
@ -1411,12 +1420,28 @@ void tst_QVariant::operator_eq_eq_data()
QVariant mUIntQString(QString("42"));
QVariant mDouble(42.11);
#ifdef QT_NO_DOUBLECONVERSION
// Without libdouble-conversion we don't get the shortest possible representation.
QVariant mDoubleString(QByteArray("42.109999999999999"));
QVariant mDoubleQString(QString("42.109999999999999"));
QVariant mDoubleQString(QByteArray("42.109999999999999"));
#else
// You cannot fool the double-to-string conversion into producing insignificant digits with
// libdouble-conversion. You can, of course, add insignificant digits to the string and fool
// the double-to-double comparison after converting the string to a double.
QVariant mDoubleString(QByteArray("42.11"));
QVariant mDoubleQString(QString("42.11"));
#endif
// Float-to-double conversion produces insignificant extra bits.
QVariant mFloat(42.11f);
QVariant mFloatString(QByteArray("42.1100006"));
QVariant mFloatQString(QString("42.1100006"));
#ifdef QT_NO_DOUBLECONVERSION
// The trailing '2' is not significant, but snprintf doesn't know this.
QVariant mFloatString(QByteArray("42.110000610351562"));
QVariant mFloatQString(QString("42.110000610351562"));
#else
QVariant mFloatString(QByteArray("42.11000061035156"));
QVariant mFloatQString(QString("42.11000061035156"));
#endif
QVariant mLongLong((qlonglong)-42);
QVariant mLongLongString(QByteArray("-42"));
@ -3374,10 +3399,11 @@ void tst_QVariant::numericalConvert()
switch (v.userType())
{
case QVariant::Double:
QCOMPARE(v.toString() , QString::number(num, 'g', DBL_MANT_DIG * std::log10(2.) + 2));
QCOMPARE(v.toString() , QString::number(num, 'g', QLocale::FloatingPointShortest));
break;
case QMetaType::Float:
QCOMPARE(v.toString() , QString::number(float(num), 'g', FLT_MANT_DIG * std::log10(2.) + 2));
QCOMPARE(v.toString() ,
QString::number(float(num), 'g', QLocale::FloatingPointShortest));
break;
}
}
@ -3613,8 +3639,17 @@ void tst_QVariant::moreCustomTypes()
QCOMPARE(MyNotMovable::count, 0);
{
#ifdef QT_NO_DOUBLECONVERSION
// snprintf cannot do "shortest" conversion and always adds noise.
PLAY_WITH_VARIANT(12.12, false, "12.119999999999999", 12.12, true);
PLAY_WITH_VARIANT(12.12f, false, "12.1199999", 12.12f, true);
#else
// Double can be printed exactly with libdouble-conversion
PLAY_WITH_VARIANT(12.12, false, "12.12", 12.12, true);
#endif
// Float is converted to double, adding insignificant bits
PLAY_WITH_VARIANT(12.12f, false, "12.119999885559082", 12.12f, true);
PLAY_WITH_VARIANT('a', false, "a", 'a', true);
PLAY_WITH_VARIANT((unsigned char)('a'), false, "a", 'a', true);
PLAY_WITH_VARIANT( quint8(12), false, "\xc", 12, true);

View File

@ -4,6 +4,10 @@ QT = core testlib core-private
embedded: QT += gui
SOURCES = ../tst_qlocale.cpp
!contains(QT_CONFIG, doubleconversion):!contains(QT_CONFIG, system-doubleconversion) {
DEFINES += QT_NO_DOUBLECONVERSION
}
TARGET = ../tst_qlocale
win32 {
CONFIG(debug, debug|release) {

View File

@ -772,20 +772,28 @@ void tst_QLocale::doubleToString_data()
QTest::addColumn<char>("mode");
QTest::addColumn<int>("precision");
QTest::newRow("C 3.4 f 5") << QString("C") << QString("3.40000") << 3.4 << 'f' << 5;
QTest::newRow("C 3.4 f 0") << QString("C") << QString("3") << 3.4 << 'f' << 0;
QTest::newRow("C 3.4 e 5") << QString("C") << QString("3.40000e+00") << 3.4 << 'e' << 5;
QTest::newRow("C 3.4 e 0") << QString("C") << QString("3e+00") << 3.4 << 'e' << 0;
QTest::newRow("C 3.4 g 5") << QString("C") << QString("3.4") << 3.4 << 'g' << 5;
QTest::newRow("C 3.4 g 1") << QString("C") << QString("3") << 3.4 << 'g' << 1;
int shortest = QLocale::FloatingPointShortest;
QTest::newRow("C 3.4 f 1") << QString("C") << QString("3.4") << 3.4 << 'f' << 1;
QTest::newRow("C 3.4 e 1") << QString("C") << QString("3.4e+00") << 3.4 << 'e' << 1;
QTest::newRow("C 3.4 g 2") << QString("C") << QString("3.4") << 3.4 << 'g' << 2;
QTest::newRow("C 3.4 f 5") << QString("C") << QString("3.40000") << 3.4 << 'f' << 5;
QTest::newRow("C 3.4 f 0") << QString("C") << QString("3") << 3.4 << 'f' << 0;
QTest::newRow("C 3.4 e 5") << QString("C") << QString("3.40000e+00") << 3.4 << 'e' << 5;
QTest::newRow("C 3.4 e 0") << QString("C") << QString("3e+00") << 3.4 << 'e' << 0;
QTest::newRow("C 3.4 g 5") << QString("C") << QString("3.4") << 3.4 << 'g' << 5;
QTest::newRow("C 3.4 g 1") << QString("C") << QString("3") << 3.4 << 'g' << 1;
QTest::newRow("de_DE 3,4 f 1") << QString("de_DE") << QString("3,4") << 3.4 << 'f' << 1;
QTest::newRow("de_DE 3,4 e 1") << QString("de_DE") << QString("3,4e+00") << 3.4 << 'e' << 1;
QTest::newRow("de_DE 3,4 g 2") << QString("de_DE") << QString("3,4") << 3.4 << 'g' << 2;
QTest::newRow("C 3.4 f 1") << QString("C") << QString("3.4") << 3.4 << 'f' << 1;
QTest::newRow("C 3.4 f -") << QString("C") << QString("3.4") << 3.4 << 'f' << shortest;
QTest::newRow("C 3.4 e 1") << QString("C") << QString("3.4e+00") << 3.4 << 'e' << 1;
QTest::newRow("C 3.4 e -") << QString("C") << QString("3.4e+00") << 3.4 << 'e' << shortest;
QTest::newRow("C 3.4 g 2") << QString("C") << QString("3.4") << 3.4 << 'g' << 2;
QTest::newRow("C 3.4 g -") << QString("C") << QString("3.4") << 3.4 << 'g' << shortest;
QTest::newRow("de_DE 3,4 f 1") << QString("de_DE") << QString("3,4") << 3.4 << 'f' << 1;
QTest::newRow("de_DE 3,4 f -") << QString("de_DE") << QString("3,4") << 3.4 << 'f' << shortest;
QTest::newRow("de_DE 3,4 e 1") << QString("de_DE") << QString("3,4e+00") << 3.4 << 'e' << 1;
QTest::newRow("de_DE 3,4 e -") << QString("de_DE") << QString("3,4e+00") << 3.4 << 'e' << shortest;
QTest::newRow("de_DE 3,4 g 2") << QString("de_DE") << QString("3,4") << 3.4 << 'g' << 2;
QTest::newRow("de_DE 3,4 g -") << QString("de_DE") << QString("3,4") << 3.4 << 'g' << shortest;
QTest::newRow("C 0.035003945 f 12") << QString("C") << QString("0.035003945000") << 0.035003945 << 'f' << 12;
QTest::newRow("C 0.035003945 f 6") << QString("C") << QString("0.035004") << 0.035003945 << 'f' << 6;
@ -794,13 +802,19 @@ void tst_QLocale::doubleToString_data()
QTest::newRow("C 0.035003945 g 11") << QString("C") << QString("0.035003945") << 0.035003945 << 'g' << 11;
QTest::newRow("C 0.035003945 g 5") << QString("C") << QString("0.035004") << 0.035003945 << 'g' << 5;
QTest::newRow("C 0.035003945 f 9") << QString("C") << QString("0.035003945") << 0.035003945 << 'f' << 9;
QTest::newRow("C 0.035003945 e 7") << QString("C") << QString("3.5003945e-02") << 0.035003945 << 'e' << 7;
QTest::newRow("C 0.035003945 g 8") << QString("C") << QString("0.035003945") << 0.035003945 << 'g' << 8;
QTest::newRow("C 0.035003945 f 9") << QString("C") << QString("0.035003945") << 0.035003945 << 'f' << 9;
QTest::newRow("C 0.035003945 f -") << QString("C") << QString("0.035003945") << 0.035003945 << 'f' << shortest;
QTest::newRow("C 0.035003945 e 7") << QString("C") << QString("3.5003945e-02") << 0.035003945 << 'e' << 7;
QTest::newRow("C 0.035003945 e -") << QString("C") << QString("3.5003945e-02") << 0.035003945 << 'e' << shortest;
QTest::newRow("C 0.035003945 g 8") << QString("C") << QString("0.035003945") << 0.035003945 << 'g' << 8;
QTest::newRow("C 0.035003945 g -") << QString("C") << QString("0.035003945") << 0.035003945 << 'g' << shortest;
QTest::newRow("de_DE 0,035003945 f 9") << QString("de_DE") << QString("0,035003945") << 0.035003945 << 'f' << 9;
QTest::newRow("de_DE 0,035003945 e 7") << QString("de_DE") << QString("3,5003945e-02") << 0.035003945 << 'e' << 7;
QTest::newRow("de_DE 0,035003945 g 8") << QString("de_DE") << QString("0,035003945") << 0.035003945 << 'g' << 8;
QTest::newRow("de_DE 0,035003945 f 9") << QString("de_DE") << QString("0,035003945") << 0.035003945 << 'f' << 9;
QTest::newRow("de_DE 0,035003945 f -") << QString("de_DE") << QString("0,035003945") << 0.035003945 << 'f' << shortest;
QTest::newRow("de_DE 0,035003945 e 7") << QString("de_DE") << QString("3,5003945e-02") << 0.035003945 << 'e' << 7;
QTest::newRow("de_DE 0,035003945 e -") << QString("de_DE") << QString("3,5003945e-02") << 0.035003945 << 'e' << shortest;
QTest::newRow("de_DE 0,035003945 g 8") << QString("de_DE") << QString("0,035003945") << 0.035003945 << 'g' << 8;
QTest::newRow("de_DE 0,035003945 g -") << QString("de_DE") << QString("0,035003945") << 0.035003945 << 'g' << shortest;
QTest::newRow("C 0.000003945 f 12") << QString("C") << QString("0.000003945000") << 0.000003945 << 'f' << 12;
QTest::newRow("C 0.000003945 f 6") << QString("C") << QString("0.000004") << 0.000003945 << 'f' << 6;
@ -809,13 +823,19 @@ void tst_QLocale::doubleToString_data()
QTest::newRow("C 0.000003945 g 7") << QString("C") << QString("3.945e-06") << 0.000003945 << 'g' << 7;
QTest::newRow("C 0.000003945 g 1") << QString("C") << QString("4e-06") << 0.000003945 << 'g' << 1;
QTest::newRow("C 0.000003945 f 9") << QString("C") << QString("0.000003945") << 0.000003945 << 'f' << 9;
QTest::newRow("C 0.000003945 e 3") << QString("C") << QString("3.945e-06") << 0.000003945 << 'e' << 3;
QTest::newRow("C 0.000003945 g 4") << QString("C") << QString("3.945e-06") << 0.000003945 << 'g' << 4;
QTest::newRow("C 0.000003945 f 9") << QString("C") << QString("0.000003945") << 0.000003945 << 'f' << 9;
QTest::newRow("C 0.000003945 f -") << QString("C") << QString("0.000003945") << 0.000003945 << 'f' << shortest;
QTest::newRow("C 0.000003945 e 3") << QString("C") << QString("3.945e-06") << 0.000003945 << 'e' << 3;
QTest::newRow("C 0.000003945 e -") << QString("C") << QString("3.945e-06") << 0.000003945 << 'e' << shortest;
QTest::newRow("C 0.000003945 g 4") << QString("C") << QString("3.945e-06") << 0.000003945 << 'g' << 4;
QTest::newRow("C 0.000003945 g -") << QString("C") << QString("3.945e-06") << 0.000003945 << 'g' << shortest;
QTest::newRow("de_DE 0,000003945 f 9") << QString("de_DE") << QString("0,000003945") << 0.000003945 << 'f' << 9;
QTest::newRow("de_DE 0,000003945 e 3") << QString("de_DE") << QString("3,945e-06") << 0.000003945 << 'e' << 3;
QTest::newRow("de_DE 0,000003945 g 4") << QString("de_DE") << QString("3,945e-06") << 0.000003945 << 'g' << 4;
QTest::newRow("de_DE 0,000003945 f 9") << QString("de_DE") << QString("0,000003945") << 0.000003945 << 'f' << 9;
QTest::newRow("de_DE 0,000003945 f -") << QString("de_DE") << QString("0,000003945") << 0.000003945 << 'f' << shortest;
QTest::newRow("de_DE 0,000003945 e 3") << QString("de_DE") << QString("3,945e-06") << 0.000003945 << 'e' << 3;
QTest::newRow("de_DE 0,000003945 e -") << QString("de_DE") << QString("3,945e-06") << 0.000003945 << 'e' << shortest;
QTest::newRow("de_DE 0,000003945 g 4") << QString("de_DE") << QString("3,945e-06") << 0.000003945 << 'g' << 4;
QTest::newRow("de_DE 0,000003945 g -") << QString("de_DE") << QString("3,945e-06") << 0.000003945 << 'g' << shortest;
QTest::newRow("C 12456789012 f 3") << QString("C") << QString("12456789012.000") << 12456789012.0 << 'f' << 3;
QTest::newRow("C 12456789012 e 13") << QString("C") << QString("1.2456789012000e+10") << 12456789012.0 << 'e' << 13;
@ -824,12 +844,18 @@ void tst_QLocale::doubleToString_data()
QTest::newRow("C 12456789012 g 8") << QString("C") << QString("1.2456789e+10") << 12456789012.0 << 'g' << 8;
QTest::newRow("C 12456789012 f 0") << QString("C") << QString("12456789012") << 12456789012.0 << 'f' << 0;
QTest::newRow("C 12456789012 f -") << QString("C") << QString("12456789012") << 12456789012.0 << 'f' << shortest;
QTest::newRow("C 12456789012 e 10") << QString("C") << QString("1.2456789012e+10") << 12456789012.0 << 'e' << 10;
QTest::newRow("C 12456789012 e -") << QString("C") << QString("1.2456789012e+10") << 12456789012.0 << 'e' << shortest;
QTest::newRow("C 12456789012 g 11") << QString("C") << QString("12456789012") << 12456789012.0 << 'g' << 11;
QTest::newRow("C 12456789012 g -") << QString("C") << QString("12456789012") << 12456789012.0 << 'g' << shortest;
QTest::newRow("de_DE 12456789012 f 0") << QString("de_DE") << QString("12.456.789.012") << 12456789012.0 << 'f' << 0;
QTest::newRow("de_DE 12456789012 f -") << QString("de_DE") << QString("12.456.789.012") << 12456789012.0 << 'f' << shortest;
QTest::newRow("de_DE 12456789012 e 10") << QString("de_DE") << QString("1,2456789012e+10") << 12456789012.0 << 'e' << 10;
QTest::newRow("de_DE 12456789012 e -") << QString("de_DE") << QString("1,2456789012e+10") << 12456789012.0 << 'e' << shortest;
QTest::newRow("de_DE 12456789012 g 11") << QString("de_DE") << QString("12.456.789.012") << 12456789012.0 << 'g' << 11;
QTest::newRow("de_DE 12456789012 g -") << QString("de_DE") << QString("12.456.789.012") << 12456789012.0 << 'g' << shortest;
}
void tst_QLocale::doubleToString()
@ -840,6 +866,11 @@ void tst_QLocale::doubleToString()
QFETCH(char, mode);
QFETCH(int, precision);
#ifdef QT_NO_DOUBLECONVERSION
if (precision == QLocale::FloatingPointShortest)
QSKIP("'Shortest' double conversion is not that short without libdouble-conversion");
#endif
const QLocale locale(locale_name);
QCOMPARE(locale.toString(num, mode, precision), num_str);