Andry
Andry

Reputation: 16845

Problems with Log function in Boost C++ libraries

I have this code in order to get a logarithm of a number given a generic base:

#include <boost/math/special_functions/powm1.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/sqrt1pm1.hpp>
// ...
// Boost Log returns boost::math::log1p(x) = log(e, x + 1)
double res = (double)(boost::math::log1p(arg - 1));
// Base conversion: log(new, y) = log(old, y) / log(old, new)
// Then ==> log(base, arg) = log(e, arg) / log(e, base)
res = (double)(res / ((double)boost::math::log1p(base - 1)));
return res;

As you can see boot libs define only neperian log and there is also a tricky way to get that log because what that lib gives back to you is not log(x) but log(x+1). As you can see this problem is solved by giving as the argument arg - 1 and everything should work.

WELL It works, but only the neperian log is ok, I mean, If I run this code:

#include <boost/math/special_functions/powm1.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/sqrt1pm1.hpp>
// ...
// Boost Log returns boost::math::log1p(x) = log(e, x + 1)
double res = (double)(boost::math::log1p(arg - 1));
// Base conversion: log(new, y) = log(old, y) / log(old, new)
// Then ==> log(base, arg) = log(e, arg) / log(e, base)
//res = (double)(res / ((double)boost::math::log1p(base - 1)));
return res;

Everything is ok, but right when I perform a base change everything is not good, I get back wrong results... I don't know, maybe it's a math issue... I know that log(basea, x) = log(baseb, x)/log(baseb, basea)...

Where do I do wrong??

Well, may be it is a math issue concerning numerical stability and so on... to get a log in a different base, what's the best practice???????

Upvotes: 1

Views: 1907

Answers (2)

sgowd
sgowd

Reputation: 1034

It is not clear what is the type of arg. You could try a few things

  1. Verify boost::math::log1p( ) prints out the expected result.

  2. Verify arg - 1 really is really a double and print it out. Instead have you tried: arg - 1.0

Upvotes: 0

CashCow
CashCow

Reputation: 31435

I am not sure what is happening exactly but you may be having a rounding issue. The issue with 1 + delta where delta is small is that doubles are not built to hold the delta to much precision as the 1 dominates enormously and the delta is considered insignificant.

The purpose of the boost library is to allow you to pass in the 1 and the delta separately to not lose the precision of the delta when you take the log, which will give you a number close to 0.

An example is you delta = 0.00000000123456789

If you add that to 1 then subtract 1 again you will not see all those numbers as a double only holds about 15 places of precision but the number above +1 gives requires 17 whereas the numbe I have printed uses just 9 places because the leading zeros don't count.

Upvotes: 1

Related Questions