# Using mpq_t for aggregating currencies with wildly varying ranges

David Gillies daggillies at gmail.com
Wed Apr 16 19:20:45 UTC 2014

```Oh lord, it's just a test harness, but if you want...

//
// de-canonicalize a pair of numbers i.e. treat them as numerator
// and denominator of a rational, assuming rational is terminating.
// Then rational a/b can be written as c/10^d
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <gmp.h>

int main(int argc,char *argv[])
{
mpz_t                a,b,c,t,five;
mp_bitcnt_t        m,n;
char                *ab,*tb;
size_t            as;

if(argc<3)
{
exit(EINVAL);
}

mpz_inits(t,c,NULL); // temporaries
mpz_init_set_ui(five,5UL); // needed for mpz_remove, grr

mpz_init_set_str(a,argv,10); // numerator
mpz_init_set_str(b,argv,10); // denominator
gmp_printf("a: %Zd\n",a);
gmp_printf("b: %Zd\n",b);

m=mpz_scan1(b,0); // power of 2 in den
n=mpz_remove(c,b,five); // power of 5
printf("m: %d\n",m);
printf("n: %d\n",n);

if(m>n)
mpz_ui_pow_ui(t,5UL,m-n); // t = 5^(m-n)
else
mpz_setbit(t,n-m); // t = 2^(n-m)

gmp_printf("t: %Zd\n",t);
mpz_mul(a,a,t); // multiply numerator by t
gmp_printf("num (decanonicalised): %Zd\n",a);
// check denominator
mpz_ui_pow_ui(c,5,n);
mpz_mul_2exp(c,c,m);
if(mpz_cmp(b,c))
{
exit(-1);
}

as=mpz_sizeinbase(a,10);
if((ab=malloc(as+2))==NULL)
{
exit(errno);
}
if((tb=malloc(as+2))==NULL)
{
exit(errno);
}
as=gmp_sprintf(ab,"%Zd",a);

m=(m>n ? m : n);
if(m>0)
{
strncpy(tb,ab,as-m);
tb[as-m]=0;
printf("\n=====> %s.%s\n",tb,ab+as-m);
}
else
printf("\n=====> %s\n",ab);

free(ab);
free(tb);

return 0;
}

Pretty ugly, I'm afraid, but it's proof of concept.

On Wed, Apr 16, 2014 at 12:33 PM, Donovan Hide <donovanhide at gmail.com>wrote:

> Thanks Phil and David for the pointers! Much appreciated. I've found that
> the simplifying of the rationals hasn't occurred when I've switched over to
> using the C interface from the C++ interface. Not sure if a canonicalise
> was hidden away somewhere in the C++ wrapper output handling...
>
> David, any chance of seeing your code? I'm just working on the decimal
> place shifting in the string output. My C is very rusty :-)
>
>

--
David Gillies
San Jose
Costa Rica
```