Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Add numbers in log domain [solved]

by pRaNaV (Novice)
on Jun 04, 2012 at 04:34 UTC ( #974222=perlquestion: print w/ replies, xml ) Need Help??
pRaNaV has asked for the wisdom of the Perl Monks concerning the following question:

Hello, is there a module in perl wherein I can do log(x + y) operation without using a high precision library(e.g. Math::GMPf/MPFR)? Only thing known to me is log(x) and log(y). Base of the logarithm is an arbitrary float (> 1). Basically the antilog operation is to be avoided to save precision. Thanks!

Comment on Add numbers in log domain [solved]
Re: Add numbers in log domain
by roboticus (Canon) on Jun 04, 2012 at 10:38 UTC

    pRaNaV:

    You'll likely have to clarify your question. As I read it, you're probably wanting to compute the logarithm of a sum using a base other than e. But since the documentation for the log function (which you can read via perldoc -f log) covers this, I'm hard pressed to imagine that's what you actually want. But if you did want that, then:

    my ($x, $y, $base) = (23.5, 54.3, 2.0); my $result = log($x + $y) / log($base); print "result: $result\n";

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      My interpretation of the OP is: Given two (log) values X & Y where both are the logs to the same (unspecified) base: B; is it possible to derive Z, such that Z = logB( B^X + B^Y ); without going through the exponentiation step.

      Eg.

      X = logB( x ) = 2.51294159473206;

      Y = logB( y ) = 2.95544864408182;

      Z = logB( x + y ) = 3.51294159473206;

      Is it possible to derive Z without discovering x & y by 'antilogging' X & Y?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      The start of some sanity?

        Sorry, for not being clear. Yes, BrowserUK is right. I wan't to know how this (log(x + y)) can be done in perl without using exponentiation (base^x, base^y etc.).

Re: Add numbers in log domain
by salva (Monsignor) on Jun 04, 2012 at 11:57 UTC
    well, suppose that x >= y, and that we are using the natural base:
    log(x + y) = log(x * (1 + y/x)) = log(x) + log(1 + y/x) y/x = exp(log(y/x)) = exp(log(y) - log(x)) log(x + y) = log(x) + log(1 + exp(log(y) - log(x)))

    And that formula can be easily calculated using regular perl scalars because log(y) - log(x) is in [-log(x), 0] and exp(log(y) - log(x)) is in (0, 1].

      Yes, something like that should work. Take the Math::Libm module, and use the expm1 and log1p functions for this. I won't figure out the correct formula now.

      Update 2012-06-10: though this won't help OP, future people who stumble this question by searching might want to look at the Math::BigApprox module.

      Spot on! (Though you do need to know the arbitrary base B):

      sub log2p5{ log( $_[0] ) / log( 2.5 ) };; $X = log2p5( 10 ); $Y = log2p5( 15 ); $Z = log2p5( 10 + 15 ); print $X, $Y, $Z;; 2.51294159473206 2.95544864408182 3.51294159473206 print 2.51294159473206 + log2p5( 1 + 2.5**( 2.95544864408182 - 2.51294 +159473206 ) );; 3.51294159473206

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      The start of some sanity?

        yes, but it is easy to convert from any base to natural, perform the computation and then convert back to the original base.

      Thanks! That will save one exponentiation step. Earlier I had to do base^x, base^y, now only one exponentiation step is required (exp(log(y) - log(x))). Btw, range for log(y) - log(x) is (-inf 0]

      As I came to learn from another source where they CREATE log table for this particular problem (function logmath_init() in http://cmusphinx.svn.sourceforge.net/viewvc/cmusphinx/trunk/sphinxbase/src/libsphinxbase/util/logmath.c?revision=11275&view=markup)

      It's like this - first set (log(y) - log(x)) = 0; then compute base^(1 + exp(log(y) - log(x))

      then decrement log(y) - log(x) by 1 (equivalent to dividing by base) and recomputing base^(1 + exp(log(y) - log(x))

      this is done untill we reach the MOST negative number. Using this table one can back-compute any log(x+y) for that particular base.

      Thanks again for your help.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://974222]
Approved by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2014-07-13 02:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (245 votes), past polls