« June 2011 | Main | April 2012 »

February 02, 2012

(Not) calculating the product of a Python list of for comparison purposes

I came across a stackoverflow question about multiplying the numbers in a Python list. Suggestions there included:

def product(list):
    p
=1
   
for i in list:
        p
*= i
   
return p

and

from operator import mul
reduce
(mul, list)

Adding my own $.02, you can also do:

import math
math
.exp(sum(map(math.log, list)))

which gets the same numerical results (at least to as way more decimal places than you're ever likely to care about, the difference being due to computational floating point errors). It's probably not as readable as the reduce-based solution, though if you're a mathematician who isn't familiar with reduce(), the opposite would be true!

(The underlying principle is that a * b * c * … * z == e ^ (ln(a) + ln(b) + ln( c) + … + ln(z)).)

I wouldn't necessarily advise using the log-based solution under normal circumstances. But if you're ever in a situation where you risk overflow or overflow, such as in

>>> reduce(mul, [10.] * 309)
inf

and your purpose is to compare the products of different sequences rather than to know specifically what the products are, then, you can accomplish your purposes without actually computing the entire product. Rather, you can compare the sums of the logs of the terms, without bothering to compute the product by taking the exponential. Whichever list has a larger sum-of-logs also has the larger product. So, following up on our previous example,

>>> sum(map(math.log, [10.] * 309))
711.49879373515785

is the way to go because it's virtually impossible to have a real-world problem in which you would overflow or underflow with this approach. (The larger the result of that calculation is, the larger the product would be if you could calculate it.)

Accordingly, if you wanted to compare 10. ^ 309 and 11. ^ 309, you could do

>>> sum(map(math.log, [10.] * 309)) > sum(map(math.log, [11.] * 309))
False

[Originally posted as "Calculating the product of a Python list. Updated for clarity and completeness.]

 

 

February 2, 2012 in Python | Permalink | Comments (0)