2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 04:42:11 +00:00

Fixing problems related to formatting numbers

This commit is contained in:
Hartmut Kaiser
2020-11-21 15:58:03 -06:00
parent e0625d190b
commit 9b126fa865
3 changed files with 47 additions and 13 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2020 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -94,24 +94,33 @@ namespace boost { namespace spirit { namespace karma
// allow for ADL to find the correct overloads for log10 et.al.
using namespace std;
bool precexp_offset = false;
U dim = 0;
if (0 == (Policies::fmtflags::fixed & flags) && !traits::test_zero(n))
{
dim = log10(n);
if (dim > 0)
if (dim > 0)
n /= spirit::traits::pow10<U>(traits::truncate_to_long::call(dim));
else if (n < 1.) {
long exp = traits::truncate_to_long::call(-dim);
if (exp != -dim)
++exp;
dim = static_cast<U>(-exp);
// detect and handle denormalized numbers to prevent overflow in pow10
if (exp > std::numeric_limits<U>::max_exponent10)
{
n *= spirit::traits::pow10<U>(std::numeric_limits<U>::max_exponent10);
n *= spirit::traits::pow10<U>(exp - std::numeric_limits<U>::max_exponent10);
} else
}
else
n *= spirit::traits::pow10<U>(exp);
if (n < 1.)
{
n *= 10.;
--dim;
precexp_offset = true;
}
}
}
@@ -120,14 +129,28 @@ namespace boost { namespace spirit { namespace karma
U precexp = spirit::traits::pow10<U>(precision);
U fractional_part = modf(n, &integer_part);
fractional_part = floor(fractional_part * precexp + U(0.5));
if (fractional_part >= precexp)
if (precexp_offset)
{
fractional_part =
floor((fractional_part * precexp + U(0.5)) * U(10.)) / U(10.);
}
else
{
fractional_part = floor(fractional_part * precexp + U(0.5));
}
if (fractional_part >= precexp)
{
fractional_part = floor(fractional_part - precexp);
integer_part += 1; // handle rounding overflow
if (integer_part >= 10.)
{
integer_part /= 10.;
++dim;
}
}
// if trailing zeros are to be omitted, normalize the precision and
// if trailing zeros are to be omitted, normalize the precision and``
// fractional part
U long_int_part = floor(integer_part);
U long_frac_part = fractional_part;

View File

@@ -100,7 +100,7 @@ int main()
BOOST_TEST(test("1.234e-05", science, 0.000012345));
BOOST_TEST(test("1.234e-04", science, 0.00012345));
BOOST_TEST(test("1.234e-03", science, 0.0012345));
BOOST_TEST(test("1.234e-02", science, 0.012345));
BOOST_TEST(test("1.235e-02", science, 0.012345));
BOOST_TEST(test("1.235e-01", science, 0.12345)); // note the rounding error!
BOOST_TEST(test("1.234e00", science, 1.2345));
BOOST_TEST(test("1.235e01", science, 12.346));
@@ -112,7 +112,7 @@ int main()
BOOST_TEST(test("-1.234e-05", science, -0.000012345));
BOOST_TEST(test("-1.234e-04", science, -0.00012345));
BOOST_TEST(test("-1.234e-03", science, -0.0012345));
BOOST_TEST(test("-1.234e-02", science, -0.012345));
BOOST_TEST(test("-1.235e-02", science, -0.012345));
BOOST_TEST(test("-1.235e-01", science, -0.12345)); // note the rounding error!
BOOST_TEST(test("-1.234e00", science, -1.2345));
BOOST_TEST(test("-1.235e01", science, -12.346));
@@ -124,7 +124,7 @@ int main()
BOOST_TEST(test("1.234E-05", upper[science], 0.000012345));
BOOST_TEST(test("1.234E-04", upper[science], 0.00012345));
BOOST_TEST(test("1.234E-03", upper[science], 0.0012345));
BOOST_TEST(test("1.234E-02", upper[science], 0.012345));
BOOST_TEST(test("1.235E-02", upper[science], 0.012345));
BOOST_TEST(test("1.235E-01", upper[science], 0.12345)); // note the rounding error!
BOOST_TEST(test("1.234E00", upper[science], 1.2345));
BOOST_TEST(test("1.235E01", upper[science], 12.346));
@@ -136,7 +136,7 @@ int main()
BOOST_TEST(test("-1.234E-05", upper[science], -0.000012345));
BOOST_TEST(test("-1.234E-04", upper[science], -0.00012345));
BOOST_TEST(test("-1.234E-03", upper[science], -0.0012345));
BOOST_TEST(test("-1.234E-02", upper[science], -0.012345));
BOOST_TEST(test("-1.235E-02", upper[science], -0.012345));
BOOST_TEST(test("-1.235E-01", upper[science], -0.12345)); // note the rounding error!
BOOST_TEST(test("-1.234E00", upper[science], -1.2345));
BOOST_TEST(test("-1.235E01", upper[science], -12.346));

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2020 Hartmut Kaiser
// Copyright (c) 2011 Bryce Lelbach
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -180,6 +180,17 @@ int main()
{
BOOST_TEST(test("4.941e-324", double_, std::numeric_limits<double>::denorm_min()));
}
// test for #628: spirit::karma::generate generates 10.0e-04, but expecting 1.0e-03
{
BOOST_TEST(test("1.0", double_, 0.99999999999999829));
BOOST_TEST(test("0.1", double_, 0.099999999999999829));
BOOST_TEST(test("0.01", double_, 0.0099999999999999829));
BOOST_TEST(test("1.0e-03", double_, 0.00099999999999999829));
BOOST_TEST(test("1.0e-04", double_, 0.00009999999999999982));
BOOST_TEST(test("1.0e-05", double_, 0.00000999999999999998));
}
return boost::report_errors();
}