Sir Whiteout
Sir Whiteout

Reputation: 133

How to use printf with mpfr and mpreal

What is the correct syntax for using printf and its cousins sprintf and fprintf to display the value of mpreal-type variables? I have tried the naive casting to double:

printf ("... %g ...", (double) var);

only to receive this error message from g++:

error: invalid cast from type ‘mpfr::mpreal’ to type ‘double’

I had no problem using double-type variables elsewhere on the program.

I heard about the type mpreal as part of this library intended to enable the use of the usual binary operators to perform arbitrary precision arithmetic operations.

Upvotes: 3

Views: 3861

Answers (2)

Pavel Holoborodko
Pavel Holoborodko

Reputation: 557

The mpreal is arbitrary precision floating-point numerical type.

As such, mpreal numbers might have much more significant digits (even hundreds or thousandths) than double. Which means it is pointless to round mpreal to double before display - you will lose all the original accuracy in this case.

It is easy to display mpreal in C++:

/* 100-digits accurate pi */
mpreal pi = mpfr::const_pi(mpfr::digits2bits(100));

/* Show 60-digits of pi */
cout.precision(60);
cout << pi;

However you can use it with printf as well (by converting to string first):

/* Display all digits (default formatting) */
printf("pi = %s\n", pi.toString().c_str());         

/* Custom format, 60 digits */
printf("pi = %s\n", pi.toString("%.60RNf").c_str());

/* Using native printf from MPFR*/
mpfr_printf("pi = %.60RNf\n", pi.mpfr_srcptr());

Format specification for multiple-precision numbers are the same as for standard with the exception to rounding specification. You can safely use rounding to nearest,RN as in examples above.

More details on mp-formatting are given in MPFR documentation.

(I'm author of mpreal class aka MPFR C++)

Upvotes: 7

Keith Thompson
Keith Thompson

Reputation: 263197

mpreal is a class, not a numeric type, and it doesn't provide conversion operators to numeric types.

But it does provide member functions that perform type conversions:

long            toLong()    const;
unsigned long   toULong()   const;
double          toDouble()  const;
long double     toLDouble() const;

So this should work:

printf ("... %g ...", var.toDouble());

or:

printf ("... %Lg ...", var.toLDouble());

(I haven't confirmed this.)

UPDATE :

An mpreal object represents a real number that may have much greater range and/or precision than can be represented by any built-in numeric type (that's the whole point of MPFR). Converting to a numeric type makes sense only if the value is within the range of that type, and you don't care about the extra precision.

In some cases, that might be good enough, but as this answer says, you can print the full precision using either the overloaded << operator or the toString() member function.

Upvotes: 2

Related Questions