diff options
author | Liang Qi <liang.qi@digia.com> | 2013-07-02 13:16:48 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-07-04 16:50:57 +0200 |
commit | 94c8efff8a46c245cd4cae1e2630c608374c442d (patch) | |
tree | 14aae57185b20a98e7e85dfc9d240d5a4293777a | |
parent | 6e8dddadd877ec8e9a8f6006e7beaa183d5da452 (diff) |
QtCore: fix the number precision in QJsonDocument.toJson() again
Need to store 17 decimal digits for binary64, IEEE 754 double formats.
Autotest is included. Test cases from TC39 test suite for ECMAScript.
Task-number: QTBUG-31926
Change-Id: I546398f21ea7ff5e40e89fc9de8703f628f55df9
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
-rw-r--r-- | src/corelib/json/qjsonwriter.cpp | 2 | ||||
-rw-r--r-- | tests/auto/corelib/json/tst_qtjson.cpp | 62 |
2 files changed, 63 insertions, 1 deletions
diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/json/qjsonwriter.cpp index b09c6dd535..3ac16c6fd1 100644 --- a/src/corelib/json/qjsonwriter.cpp +++ b/src/corelib/json/qjsonwriter.cpp @@ -170,7 +170,7 @@ static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value & json += v.toBoolean() ? "true" : "false"; break; case QJsonValue::Double: - json += QByteArray::number(v.toDouble(b), 'g', 13); + json += QByteArray::number(v.toDouble(b), 'g', 17); break; case QJsonValue::String: json += '"'; diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index 6f5cda5307..bdf8c86442 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <QtTest> + #include "qjsonarray.h" #include "qjsonobject.h" #include "qjsonvalue.h" @@ -62,6 +63,8 @@ private Q_SLOTS: void testValueSimple(); void testNumbers(); + void testNumbers_2(); + void testNumbers_3(); void testObjectSimple(); void testObjectSmallKeys(); @@ -329,6 +332,65 @@ void tst_QtJson::testNumbers() } +void tst_QtJson::testNumbers_2() +{ + // test cases from TC39 test suite for ECMAScript + // http://hg.ecmascript.org/tests/test262/file/d067d2f0ca30/test/suite/ch08/8.5/8.5.1.js + + // Fill an array with 2 to the power of (0 ... -1075) + double value = 1; + double floatValues[1076], floatValues_1[1076]; + QJsonObject jObject; + for (int power = 0; power <= 1075; power++) { + floatValues[power] = value; + jObject.insert(QString::number(power), QJsonValue(floatValues[power])); + // Use basic math operations for testing, which are required to support 'gradual underflow' rather + // than Math.pow etc..., which are defined as 'implementation dependent'. + value = value * 0.5; + } + + QJsonDocument jDocument1(jObject); + QByteArray ba(jDocument1.toJson()); + + QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); + for (int power = 0; power <= 1075; power++) { + floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble(); + QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1()); + } + + // The last value is below min denorm and should round to 0, everything else should contain a value + QVERIFY2(floatValues_1[1075] == 0, "Value after min denorm should round to 0"); + + // Validate the last actual value is min denorm + QVERIFY2(floatValues_1[1074] == 4.9406564584124654417656879286822e-324, QString("Min denorm value is incorrect: %1").arg(floatValues_1[1074]).toLatin1()); + + // Validate that every value is half the value before it up to 1 + for (int index = 1074; index > 0; index--) { + QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1()); + + QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1()); + } +} + +void tst_QtJson::testNumbers_3() +{ + // test case from QTBUG-31926 + double d1 = 1.123451234512345; + double d2 = 1.123451234512346; + + QJsonObject jObject; + jObject.insert("d1", QJsonValue(d1)); + jObject.insert("d2", QJsonValue(d2)); + QJsonDocument jDocument1(jObject); + QByteArray ba(jDocument1.toJson()); + + QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); + + double d1_1(jDocument2.object().value("d1").toDouble()); + double d2_1(jDocument2.object().value("d2").toDouble()); + QVERIFY(d1_1 != d2_1); +} + void tst_QtJson::testObjectSimple() { QJsonObject object; |