Reputation: 275
Question: While migrating some code to Boost Multiprecision, from a home-brewed OOP-wrapper around MPFI, I noticed that printing a variable precision Boost number into an output stream apparently ignores the stream's precision parameter. In fact, the behavior for variable precision is the same as for precision of 20
, regardless of the actual precision of the number. If this is the intended behavior instead of a bug, then I am curious if anyone can shed light on the rationale behind it.
Additional background: When using a fixed precision type such as mpfi_float_100
, printing the interval shows all digits up to the specified stream precision. However, when using the variable precision type mpfi_float
set to the same precision of 100
, printing the interval shows a small fraction of the digits, seemingly ignoring the stream precision. Importantly, printing the lower/upper bounds directly shows all expected digits, exactly matching the output observed in the fixed precision case (except when precision is less than 20, since that seems to be the minimum precision for variable precision mpfi_float
).
Here is a small sample program that highlights the observed behavior:
#include <boost/multiprecision/mpfi.hpp>
#include <iostream>
int main(int argc, char** argv)
{
constexpr unsigned TESTPREC = 100;
using namespace std;
using namespace boost::multiprecision;
cout.precision(5000);
// Printing a fixed precision number always displays maximum digits when output
number<mpfi_float_backend<TESTPREC>> a = 2;
number<mpfi_float_backend<TESTPREC>> root_a = sqrt(a);
cout << root_a << endl; // prints bounds at 332 and 334 digits, respectively
cout << lower(root_a) << endl; // prints 332 digits for lower bound
cout << upper(root_a) << endl; // prints 334 digits for upper bound
cout << endl;
// Printing a variable precision number may not display all digits when output
mpfi_float b = 2;
mpfi_float::default_precision(TESTPREC);
mpfi_float root_b = sqrt(b);
cout << root_b << endl; // prints bounds at just 68 and 67 digits, respectively
cout << lower(root_b) << endl; // prints 332 digits for lower bound
cout << upper(root_b) << endl; // prints 334 digits for upper bound
cout << endl;
return 0;
}
Here is a table summarizing the behavior I observed for several precision values:
Prec Type | TESTPREC | Lower digits | Upper digits | Sig. digits |
---|---|---|---|---|
Variable | Any | 68 | 67 | 19 |
Fixed | 10 | 35 | 30 | 11 |
Fixed | 20 | 68 | 67 | 19 |
Fixed | 50 | 168 | 167 | 50 |
Fixed | 100 | 332 | 334 | 101 |
Fixed | 500 | 1663 | 1662 | 501 |
Fixed | 1000 | 3324 | 3323 | 1001 |
My build environment:
/std:c++20
, /permissive-
, and /fp:strict
Thanks to everyone who takes the time to read this.
Upvotes: 1
Views: 46