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)
{
printf("bad args\n");
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[1],10); // numerator
mpz_init_set_str(b,argv[2],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))
{
printf("Bad denominator\n");
exit(-1);
}
as=mpz_sizeinbase(a,10);
if((ab=malloc(as+2))==NULL)
{
perror("bad alloc (ab)");
exit(errno);
}
if((tb=malloc(as+2))==NULL)
{
perror("bad alloc (tb)");
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
More information about the gmp-discuss
mailing list