I'm using cpp_dec_float
for arbitrary precision, and it's great, but I'm having trouble figuring out how to print all significant digits.
For example, with this code to setup
using boost::multiprecision::cpp_dec_float;
typedef boost::multiprecision::number<cpp_dec_float<100>> mp_type;
mp_type test_num("7.0710678118654752440084436210484903928483593768847403658833986900e-01");
and if I simply print with
std::cout << std::scientific << test_num << std::endl;
the result is 7.071068e-01
, so that's out.
If I go for broke with
std::cout << std::setprecision(std::numeric_limits<mp_type>::digits) << std::scientific << test_num << std::endl;
I get 7.0710678118654752440084436210484903928483593768847403658833986900000000000000000000000000000000000000e-01
. I'm happy not to lose the precision, but it's not very space conservative.
Is there a way to remove the trailing zeros without losing any precision with existing tools? If not, how can the trailing zeros be removed from the resultant string?
If existing tools can be used to satisfy my intent, how can cpp_dec_float
be output in scientific notation without lost precision and trailing zeros removed to a string? I can only find the stream examples.
Closer
Thanks to mockinterface, I'm much closer.
I've changed the code to this:
using boost::multiprecision::cpp_dec_float;
typedef boost::multiprecision::number<cpp_dec_float<0>> mp_type;
mp_type test_num("7.0710678118654752440084436210484903928483593768847403658833986900e-01");
std::cout << test_num.str(0, std::ios_base::scientific) << std::endl;
To have potentially unlimited length; however, this is printed:
7.0710678118654752440084436210484903928480e-01
Which is close but seems strange. In the source mockinterface so graciously pointed out to me, I found these lines
if(number_of_digits == 0)
number_of_digits = cpp_dec_float_total_digits10;
which suggests to me that it should take into account all significant digits, basically outputting what was input because of the unlimited length.
I checked the source for cpp_dec_float_total_digits10
, and I am unable to determine exactly what it is; although, I did find this code section that seems to define it.
private:
static const boost::int32_t cpp_dec_float_elem_digits10 = 8L;
static const boost::int32_t cpp_dec_float_elem_mask = 100000000L;
BOOST_STATIC_ASSERT(0 == cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10);
// There are three guard limbs.
// 1) The first limb has 'play' from 1...8 decimal digits.
// 2) The last limb also has 'play' from 1...8 decimal digits.
// 3) One limb can get lost when justifying after multiply,
// as only half of the triangle is multiplied and a carry
// from below is missing.
static const boost::int32_t cpp_dec_float_elem_number_request = static_cast<boost::int32_t>((cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + (((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 : 0));
// The number of elements needed (with a minimum of two) plus three added guard limbs.
static const boost::int32_t cpp_dec_float_elem_number = static_cast<boost::int32_t>(((cpp_dec_float_elem_number_request < 2L) ? 2L : cpp_dec_float_elem_number_request) + 3L);
public:
static const boost::int32_t cpp_dec_float_total_digits10 = static_cast<boost::int32_t>(cpp_dec_float_elem_number * cpp_dec_float_elem_digits10);
Can the number of significant digits be determined and used as the first argument for boost::multiprecision::cpp_dec_float::str()
?