<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: A quick assessment of factorial functions in Python</title>
	<atom:link href="http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/feed/" rel="self" type="application/rss+xml" />
	<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/</link>
	<description>a step-by-step guide to create Python applications in bioinformatics</description>
	<lastBuildDate>Mon, 22 Feb 2010 18:22:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=3.0-alpha</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Recent URLs tagged Scipy - Urlrecorder</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-2/#comment-20794</link>
		<dc:creator>Recent URLs tagged Scipy - Urlrecorder</dc:creator>
		<pubDate>Thu, 06 Nov 2008 20:31:43 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-20794</guid>
		<description>[...] recorded first by mrklaw on 2008-11-06&#8594; Paulo Nuin: A quick assessment of factorial functions in Python [...]</description>
		<content:encoded><![CDATA[<p>[...] recorded first by mrklaw on 2008-11-06&rarr; Paulo Nuin: A quick assessment of factorial functions in Python [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Paulo Nuin</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14210</link>
		<dc:creator>Paulo Nuin</dc:creator>
		<pubDate>Sun, 08 Jun 2008 02:40:43 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14210</guid>
		<description>Hi Dave

If you want send me the code in an email (nuin at genedrift dot org) and I can post it. I still didn&#039;t find a way to make the comments &quot;code-friendly&quot;.

Thanks</description>
		<content:encoded><![CDATA[<p>Hi Dave</p>
<p>If you want send me the code in an email (nuin at genedrift dot org) and I can post it. I still didn&#8217;t find a way to make the comments &#8220;code-friendly&#8221;.</p>
<p>Thanks</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Beach</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14209</link>
		<dc:creator>David Beach</dc:creator>
		<pubDate>Sun, 08 Jun 2008 02:13:10 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14209</guid>
		<description>Ok, I give up.  Very sorry about the comment spam.  Moderator, if there&#039;s a better way to express what I&#039;m trying to say, please feel free to remove most of these comments.  I&#039;d rather post the code in a readable and useful way, but I&#039;m at a total loss of how to do this.</description>
		<content:encoded><![CDATA[<p>Ok, I give up.  Very sorry about the comment spam.  Moderator, if there&#8217;s a better way to express what I&#8217;m trying to say, please feel free to remove most of these comments.  I&#8217;d rather post the code in a readable and useful way, but I&#8217;m at a total loss of how to do this.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Beach</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14208</link>
		<dc:creator>David Beach</dc:creator>
		<pubDate>Sun, 08 Jun 2008 02:10:53 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14208</guid>
		<description>Okay, now I&#039;m just testing things.  Things I would probably know if I posted comments on blogs very often:


Does this look like formatted code:  &amp; &lt; &gt; + - / *
   INDENTED LINE
FLUSH LEFT
 blah
</description>
		<content:encoded><![CDATA[<p>Okay, now I&#8217;m just testing things.  Things I would probably know if I posted comments on blogs very often:</p>
<p>Does this look like formatted code:  &amp; &lt; &gt; + &#8211; / *<br />
   INDENTED LINE<br />
FLUSH LEFT<br />
 blah</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Beach</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14207</link>
		<dc:creator>David Beach</dc:creator>
		<pubDate>Sun, 08 Jun 2008 02:08:31 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14207</guid>
		<description>Ah beautiful, the instructions still didn&#039;t come through.  I should have realized this would happen.  Let&#039;s try:

print s.replace(&quot;_LT_&quot;, chr(60)).replace(&quot;_GT_&quot;, chr(62)).replace(&quot;...&quot;, &quot; &quot;)</description>
		<content:encoded><![CDATA[<p>Ah beautiful, the instructions still didn&#8217;t come through.  I should have realized this would happen.  Let&#8217;s try:</p>
<p>print s.replace(&#8220;_LT_&#8221;, chr(60)).replace(&#8220;_GT_&#8221;, chr(62)).replace(&#8220;&#8230;&#8221;, &#8221; &#8220;)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Beach</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14206</link>
		<dc:creator>David Beach</dc:creator>
		<pubDate>Sun, 08 Jun 2008 02:04:22 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14206</guid>
		<description>Here&#039;s an experiment.  I hope it works.
To get the code, run the following python:

s.replace(&quot;_LT_&quot;, &quot;&quot;, &quot;_GT_&quot;).replace(&quot;...&quot;, &quot; &quot;)

where s is a string containing everything between BEGIN and END.

BEGIN
import...operator

def...factA(n):
............m...=...operator.mul
............return...reduce(operator.mul,...xrange(2,...n+1),...1)

def...factB(n):
............limit...=...1..._LT__LT_...(1..._LT__LT_...10)......#...limit...found...experimentally...via...timing...tests
............terms...=...[...]
............accum...=...1
............for...i...in...range(2,...n+1):
........................accum...*=...i
........................if...accum..._GT_...limit:
....................................terms.append(accum)
....................................accum...=...1
............if...accum..._GT_...1:
........................terms.append(accum)
............return...pairwise_reduce(operator.mul,...terms)

def...pairwise_reduce(op,...terms):
............while...len(terms)..._GT_...1:
........................if...len(terms)...%...2...==...0:
....................................terms...=...map(op,...terms[0::2],...terms[1::2])
........................else:
....................................terms...=...map(op,...terms[0:-1:2],...terms[1:-1:2])...+...[terms[-1]]
............return...terms[0]

def...test(n):
............for...i...in...range(2,...n):
........................if...i...%...1000...==...0:
....................................print...&quot;testing...at...%i...&quot;...%...i
........................x...=...factA(i)
........................y...=...factB(i)
........................if...x...!=...y:
....................................print...&quot;factB...failed...at...%i&quot;...%...i
....................................break

if...__name__...==...&#039;__main__&#039;:
............test(5000)
END</description>
		<content:encoded><![CDATA[<p>Here&#8217;s an experiment.  I hope it works.<br />
To get the code, run the following python:</p>
<p>s.replace(&#8220;_LT_&#8221;, &#8220;&#8221;, &#8220;_GT_&#8221;).replace(&#8220;&#8230;&#8221;, &#8221; &#8220;)</p>
<p>where s is a string containing everything between BEGIN and END.</p>
<p>BEGIN<br />
import&#8230;operator</p>
<p>def&#8230;factA(n):<br />
&#8230;&#8230;&#8230;&#8230;m&#8230;=&#8230;operator.mul<br />
&#8230;&#8230;&#8230;&#8230;return&#8230;reduce(operator.mul,&#8230;xrange(2,&#8230;n+1),&#8230;1)</p>
<p>def&#8230;factB(n):<br />
&#8230;&#8230;&#8230;&#8230;limit&#8230;=&#8230;1&#8230;_LT__LT_&#8230;(1&#8230;_LT__LT_&#8230;10)&#8230;&#8230;#&#8230;limit&#8230;found&#8230;experimentally&#8230;via&#8230;timing&#8230;tests<br />
&#8230;&#8230;&#8230;&#8230;terms&#8230;=&#8230;[...]<br />
&#8230;&#8230;&#8230;&#8230;accum&#8230;=&#8230;1<br />
&#8230;&#8230;&#8230;&#8230;for&#8230;i&#8230;in&#8230;range(2,&#8230;n+1):<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;accum&#8230;*=&#8230;i<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;if&#8230;accum&#8230;_GT_&#8230;limit:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;terms.append(accum)<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;accum&#8230;=&#8230;1<br />
&#8230;&#8230;&#8230;&#8230;if&#8230;accum&#8230;_GT_&#8230;1:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;terms.append(accum)<br />
&#8230;&#8230;&#8230;&#8230;return&#8230;pairwise_reduce(operator.mul,&#8230;terms)</p>
<p>def&#8230;pairwise_reduce(op,&#8230;terms):<br />
&#8230;&#8230;&#8230;&#8230;while&#8230;len(terms)&#8230;_GT_&#8230;1:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;if&#8230;len(terms)&#8230;%&#8230;2&#8230;==&#8230;0:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;terms&#8230;=&#8230;map(op,&#8230;terms[0::2],&#8230;terms[1::2])<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;else:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;terms&#8230;=&#8230;map(op,&#8230;terms[0:-1:2],&#8230;terms[1:-1:2])&#8230;+&#8230;[terms[-1]]<br />
&#8230;&#8230;&#8230;&#8230;return&#8230;terms[0]</p>
<p>def&#8230;test(n):<br />
&#8230;&#8230;&#8230;&#8230;for&#8230;i&#8230;in&#8230;range(2,&#8230;n):<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;if&#8230;i&#8230;%&#8230;1000&#8230;==&#8230;0:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;print&#8230;&#8221;testing&#8230;at&#8230;%i&#8230;&#8221;&#8230;%&#8230;i<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;x&#8230;=&#8230;factA(i)<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;y&#8230;=&#8230;factB(i)<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;if&#8230;x&#8230;!=&#8230;y:<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;print&#8230;&#8221;factB&#8230;failed&#8230;at&#8230;%i&#8221;&#8230;%&#8230;i<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;break</p>
<p>if&#8230;__name__&#8230;==&#8230;&#8217;__main__&#8217;:<br />
&#8230;&#8230;&#8230;&#8230;test(5000)<br />
END</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Beach</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14204</link>
		<dc:creator>David Beach</dc:creator>
		<pubDate>Sun, 08 Jun 2008 01:46:18 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14204</guid>
		<description>Ah, loss of indentation.  And parts of my code have disappeared, as well.  Is this indicative of bad character escaping?

Let me know how to fix this, and I&#039;ll re-post the algorithm.</description>
		<content:encoded><![CDATA[<p>Ah, loss of indentation.  And parts of my code have disappeared, as well.  Is this indicative of bad character escaping?</p>
<p>Let me know how to fix this, and I&#8217;ll re-post the algorithm.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Beach</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14203</link>
		<dc:creator>David Beach</dc:creator>
		<pubDate>Sun, 08 Jun 2008 01:42:33 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14203</guid>
		<description>Here&#039;s a faster implementation for large N.  This takes into account that the real cost here is the cost of multiplying two bigints (python long objects).  The goal is to keep the terms involved below a limit, until as late in the game as is possible.

def fastfact(n):
    limit = 1 &lt;&lt; (1 &lt; limit:
            terms.append(accum)
            accum = 1
    if accum &gt; 1:
        terms.append(accum)
    return pairwise_reduce(operator.mul, terms)

def pairwise_reduce(op, terms):
    while len(terms) &gt; 1:
        if len(terms) % 2 == 0:
            terms = map(op, terms[0::2], terms[1::2])
        else:
            terms = map(op, terms[0:-1:2], terms[1:-1:2]) + [terms[-1]]
    return terms[0]

On my machine, this algorithm takes:
100 loops, best of 3: 7.29 msec per loop

Whereas fact_03 takes:
100 loops, best of 3: 11.8 msec per loop

This differences become more staggering for larger n.</description>
		<content:encoded><![CDATA[<p>Here&#8217;s a faster implementation for large N.  This takes into account that the real cost here is the cost of multiplying two bigints (python long objects).  The goal is to keep the terms involved below a limit, until as late in the game as is possible.</p>
<p>def fastfact(n):<br />
    limit = 1 &lt;&lt; (1 &lt; limit:<br />
            terms.append(accum)<br />
            accum = 1<br />
    if accum &gt; 1:<br />
        terms.append(accum)<br />
    return pairwise_reduce(operator.mul, terms)</p>
<p>def pairwise_reduce(op, terms):<br />
    while len(terms) &gt; 1:<br />
        if len(terms) % 2 == 0:<br />
            terms = map(op, terms[0::2], terms[1::2])<br />
        else:<br />
            terms = map(op, terms[0:-1:2], terms[1:-1:2]) + [terms[-1]]<br />
    return terms[0]</p>
<p>On my machine, this algorithm takes:<br />
100 loops, best of 3: 7.29 msec per loop</p>
<p>Whereas fact_03 takes:<br />
100 loops, best of 3: 11.8 msec per loop</p>
<p>This differences become more staggering for larger n.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mike Hansen</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14156</link>
		<dc:creator>Mike Hansen</dc:creator>
		<pubDate>Fri, 06 Jun 2008 18:39:28 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14156</guid>
		<description>Sage ( a really big Python module with a lot of math functionality http://www.sagemath.org ) also provides its own wrapper over GMP integers:

sage: timeit(&quot;factorial(4000)&quot;)
625 loops, best of 3: 502 µs per loop
sage: timeit(&quot;factorial(40000)&quot;)
25 loops, best of 3: 27.5 ms per loop

--Mike</description>
		<content:encoded><![CDATA[<p>Sage ( a really big Python module with a lot of math functionality <a href="http://www.sagemath.org" rel="nofollow">http://www.sagemath.org</a> ) also provides its own wrapper over GMP integers:</p>
<p>sage: timeit(&#8220;factorial(4000)&#8221;)<br />
625 loops, best of 3: 502 µs per loop<br />
sage: timeit(&#8220;factorial(40000)&#8221;)<br />
25 loops, best of 3: 27.5 ms per loop</p>
<p>&#8211;Mike</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Paulo Nuin</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14155</link>
		<dc:creator>Paulo Nuin</dc:creator>
		<pubDate>Fri, 06 Jun 2008 18:19:30 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14155</guid>
		<description>Hi Andrew, 

Yep, I forgot about that one. I was going to test that function too but decided not. The extra modules that I was referring to were the gmpy and another that uses the scipy (http://aspn.activestate.com/ASPN/Mail/Message/python-list/2954844). 

In my opnion the precomputing everything is the fastest one, as I did with C++.

I will update the post. Sorry about that.</description>
		<content:encoded><![CDATA[<p>Hi Andrew, </p>
<p>Yep, I forgot about that one. I was going to test that function too but decided not. The extra modules that I was referring to were the gmpy and another that uses the scipy (<a href="http://aspn.activestate.com/ASPN/Mail/Message/python-list/2954844" rel="nofollow">http://aspn.activestate.com/ASPN/Mail/Message/python-list/2954844</a>). </p>
<p>In my opnion the precomputing everything is the fastest one, as I did with C++.</p>
<p>I will update the post. Sorry about that.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Dalke</title>
		<link>http://python.genedrift.org/2008/06/06/a-quick-assessment-of-factorial-functions-in-python/comment-page-1/#comment-14153</link>
		<dc:creator>Andrew Dalke</dc:creator>
		<pubDate>Fri, 06 Jun 2008 17:47:40 +0000</pubDate>
		<guid isPermaLink="false">http://python.genedrift.org/?p=113#comment-14153</guid>
		<description>Extra modules for the combinatorial functions?  I gave two links to Python functions for choose(n, k).  The one from Jussi Piitulainen was


def choose(n, k):
   if 0 &lt;= k &lt;= n:
       ntok = 1
       ktok = 1
       for t in xrange(1, min(k, n - k) + 1):
          ntok *= n
          ktok *= t
          n -= 1
       return ntok // ktok
   else:
       return 0


(I hope that comes out in the blog formatting.  See http://groups.google.com/group/comp.lang.python/msg/6e7c3358b086ff9c?dmode=source )

For small numbers, like all choose(n,k) where 0 &lt;= k &lt;= n &lt;= 800 then you might as well precompute everything, or use cariaso&#039;s suggestion of memoizing.</description>
		<content:encoded><![CDATA[<p>Extra modules for the combinatorial functions?  I gave two links to Python functions for choose(n, k).  The one from Jussi Piitulainen was</p>
<p>def choose(n, k):<br />
   if 0 &lt;= k &lt;= n:<br />
       ntok = 1<br />
       ktok = 1<br />
       for t in xrange(1, min(k, n &#8211; k) + 1):<br />
          ntok *= n<br />
          ktok *= t<br />
          n -= 1<br />
       return ntok // ktok<br />
   else:<br />
       return 0</p>
<p>(I hope that comes out in the blog formatting.  See <a href="http://groups.google.com/group/comp.lang.python/msg/6e7c3358b086ff9c?dmode=source" rel="nofollow">http://groups.google.com/group/comp.lang.python/msg/6e7c3358b086ff9c?dmode=source</a> )</p>
<p>For small numbers, like all choose(n,k) where 0 &lt;= k &lt;= n &lt;= 800 then you might as well precompute everything, or use cariaso&#8217;s suggestion of memoizing.</p>
]]></content:encoded>
	</item>
</channel>
</rss>

