Using mpq_t for aggregating currencies with wildly varying ranges

Donovan Hide donovanhide at gmail.com
Tue Apr 15 21:36:18 UTC 2014


Hi Paul,

thanks very much for this clever tip! Almost too clever for the
bit-twiddling part of my brain to deal with :-)

Unfortunately it does look like gmp is simplifying the fractions in some
cases, even though I'm not calling canonicalize() anywhere...

Should I be looking at mpfr instead, or can I hack this some other way?
Feels like there's a missing method on the rational type for this set of
cases...

Cheers,
Donovan.





On 15 April 2014 16:57, Zimmermann Paul <Paul.Zimmermann at inria.fr> wrote:

>        Dear Donovan,
>
> > Date: Tue, 15 Apr 2014 16:28:32 +0100
> > From: Donovan Hide <donovanhide at gmail.com>
> >
> > Hi,
> >
> > I've been doing some work on making the Ripple Currency format
> aggregatable
> > in MySQL by writing a parser and summation functions for this currency
> > format:
> >
> > https://ripple.com/wiki/Currency_Format
> >
> > The docs aren't great! The issue I've got is that I have an mpq_t
> variable
> > to which I'm adding various transaction amounts which have hugely
> variable
> > exponents, which works well and gives exact results. All denominators are
> > always powers of ten. However when it comes to outputting the value as a
> > decimal string, I've been doing something like:
> >
> > mpq_class total=make_rational(bigendian_decode(args->args[0]));
> > *length=gmp_sprintf(result,"%.Ff",mpf_class(total,100).get_mpf_t());
> >
> > which suffers from floating point drift and isn't accurate. I've been
> > looking at how pgmp for postgres solve the same problem and it's a bit
> > messy, using integers rather than rationals:
> >
> >
> https://github.com/dvarrazzo/pgmp/blob/7ed7844737c5e9c9b1ad72c255ef5a94670ec55c/src/pmpq_io.c#L329-L412
> >
> > Does anyone have any suggestions on how to format rationals as exact
> > decimals, with the proviso that the denominator is always a power of ten
> > and thus the number should be non-recurring?
> >
> > Cheers,
> > Donovan.
>
> if the denominator q is 10^n, then you can get n by mpz_scan1 (q, 0).
> Then call mpz_get_str (NULL, 10, p) to output the numerator p in a
> string, and shift the decimal point by n places to the left.
> But beware that GMP might simplify the fraction p/q and then q might
> not be exactly a power of 10.
>
> Paul Zimmermann
>


More information about the gmp-discuss mailing list