Reputation: 16845
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
Reputation: 1034
It is not clear what is the type of arg. You could try a few things
Verify boost::math::log1p( ) prints out the expected result.
Verify arg - 1 really is really a double and print it out. Instead have you tried: arg - 1.0
Upvotes: 0
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