diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2022-02-15 09:20:52 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2022-02-17 21:46:58 +0100 |
commit | 9eb9083ff2fdaeb96399a0830a4394de4e29ef64 (patch) | |
tree | 046cc63551286fb3e59c6b79ebeea505a23b2eb0 /sal/qa | |
parent | ee373f34ae1509e8d9fffaf4b5140ee9c35e8d41 (diff) |
Use Dragonbox to implement doubleTo*String*
This header-only library is accurate in decimal representation of
doubles; provides API that allows to create custom representation
- so it's possible to use custom decimal separators and grouping.
This allows to unify all corner cases: integers, numbers close to
DBL_MAX, up-rounding to the next decade.
Note that Dragonbox creates the shortest decimal representation
of the number, that is unambiguously convertible back to the same
number; thus it may hide trailing digits that are unneeded for
such conversion.
The functional changes are minimal, and beneficial:
1. Rounding numbers close to DBL_MAX now takes into account the
bEraseTrailingDecZeros argument, as it should, allowing to have
"1.8E+308" for rounding DBL_MAX to 2 decimals without trailing
zeroes, instead of previous "1.80E+308".
2. Incorrect rounding is fixed in some cases, e.g. 9.9999999999999929
rounded to 10 previously using rtl_math_DecimalPlaces_Max.
3. Representing the number in the shortest way may change display
of some printed numbers. E.g., 5th greatest double is represented
as "1.797693134862315E+308" instead of a bit longer, but giving
the same double on roundtrip, "1.7976931348623149E+308". This would
generally look better for some numbers similar to the famous 0.1,
where users would likely expect more "round" representation where
it's unambiguous (but we still truncate to 15 significant decimals
anyway - so there's no point in pretending to provide exact digits
for actual binary representation).
These are reflected in the unit tests affected by the change.
Change-Id: I05e20274a30eec499593ee3e9ec070e1269232a2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129948
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sal/qa')
-rw-r--r-- | sal/qa/rtl/math/test-rtl-math.cxx | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/sal/qa/rtl/math/test-rtl-math.cxx b/sal/qa/rtl/math/test-rtl-math.cxx index aaadccc8e97c..94840dbdb7e8 100644 --- a/sal/qa/rtl/math/test-rtl-math.cxx +++ b/sal/qa/rtl/math/test-rtl-math.cxx @@ -432,7 +432,8 @@ public: fVal = std::nextafter( fVal, 0); aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); - CPPUNIT_ASSERT_EQUAL( OUString("1.7976931348623149E+308"), aRes); + CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862315E+308"), aRes); + CPPUNIT_ASSERT_EQUAL(fVal, rtl::math::stringToDouble(aRes, '.', ',')); // Test roundtrip // DBL_MAX and 4 nextafters rounded to 15 decimals fVal = DBL_MAX; @@ -463,24 +464,20 @@ public: // DBL_MAX rounded to 2 decimals fVal = DBL_MAX; aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 2, '.', true); - CPPUNIT_ASSERT_EQUAL( OUString("1.80E+308"), aRes); + CPPUNIT_ASSERT_EQUAL( OUString("1.8E+308"), aRes); // Crashed after commit eae24a9488814e77254d175c11fc4a138c1dbd30 fVal = 123456.789; aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_E, 2, '.', false); CPPUNIT_ASSERT_EQUAL(OUString("1.23E+005"), aRes); - // Testing "after-treatment of up-rounding to the next decade" branch - // See void doubleToString in sal/rtl/math.cxx - // 1. Yet empty buffer fVal = 9.9999999999999929; aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); - CPPUNIT_ASSERT_EQUAL(OUString("10"), aRes); + CPPUNIT_ASSERT_EQUAL(OUString("9.99999999999999"), aRes); - // 2. Buffer with some content fVal = 0.99999999999999933; aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_F, rtl_math_DecimalPlaces_Max, '.', true); - CPPUNIT_ASSERT_EQUAL(OUString("1"), aRes); + CPPUNIT_ASSERT_EQUAL(OUString("0.999999999999999"), aRes); } void test_approx() { |