I'd avoid pow
for this. It's notoriously hard to implement correctly. There are lots of SO questions where people got burned by a bad pow
implementation in their standard library.
You can also save yourself a good deal of pain by working in the natural base instead of base 10. You'll get code that looks like this:
long double foo = m * logl(n);
foo = fmodl(foo, logl(10.0)) + some_epsilon;
sprintf(some_string, "%.9Lf", expl(foo));
/* boring string parsing code here */
to compute the appropriate analogue of m log(n)
. Notice that the largest m * logl(n)
that can arise is just a little bigger than 2e10
. When you divide that by 264 and round up to the nearest power of two, you see that an ulp of foo
is 2-29 at worst. This means, in particular, that you cannot get more than 8 digits out of this method using long double
s, even with a perfect implementation.
some_epsilon
will be the smallest long double
that makes expl(foo)
always exceed the mathematically correct result; I haven't computed it exactly, but it should be on the order of 1e-9
.
In light of the precision difficulties here, I might suggest using a library like MPFR instead of long double
s. You may also be able to get something to work using a double double
trick and quad-precision exp
, log
, and fmod
.