Using mpq_t for aggregating currencies with wildly varying ranges

Zimmermann Paul Paul.Zimmermann at inria.fr
Tue Apr 15 15:57:11 UTC 2014


       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