Computing Combinatorial Functions

Problem

You need to compute the number of permutations or combinations of size r of a given set.

Solution

If you know the formula for permutations of size r is N! / r! and you know that the formula for combinations is N! / r! * (N-r)!, then you might disregard this example; this book already gave an example for factorial. However, since factorials get very big quickly, you need to be a little crafty to get the best bang for your calculating buck:

<xsl:template name="math:P">
     <xsl:param name="n" select="1"/>
     <xsl:param name="r" select="1"/>
      <xsl:choose>
        <xsl:when test="$n &lt; 0 or $r &lt; 0">NaN</xsl:when>
        <xsl:when test="$n = 0">0</xsl:when>
        <xsl:otherwise>
               <xsl:call-template name="prod-range">
               <xsl:with-param name="start" select="$r + 1"/>
               <xsl:with-param name="end" select="$n"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
</xsl:template>
   
<xsl:template name="math:C">
     <xsl:param name="n" select="1"/>
     <xsl:param name="r" select="1"/>
      <xsl:choose>
        <xsl:when test="$n &lt; 0 or $r &lt; 0">NaN</xsl:when>
        <xsl:when test="$n = 0">0</xsl:when>
        <xsl:otherwise>
          <xsl:variable name="min" 
               select="($r &lt;= $n - $r) * $r +  ($r > $n - $r) * $n - $r"/>
          <xsl:variable name="max" 
               select="($r >= $n - $r) * $r +  ($r &lt; $n - $r) * $n - $r"/>
          <xsl:variable name="numerator">
            <xsl:call-template name="prod-range">
                 <xsl:with-param name="start" select="$max + 1"/>
                 <xsl:with-param name="end" select="$n"/>
            </xsl:call-template>
          </xsl:variable>
          <xsl:variable name="denominator">
            <xsl:call-template name="math:fact">
              <xsl:with-param name="number" select="$min"/>
            </xsl:call-template>
          </xsl:variable>
          <xsl:value-of select="$numerator div $denominator"/>
        </xsl:otherwise>
      </xsl:choose>
</xsl:template>

Discussion

The solutions are designed to reduce the number of multiplications; if you divide one factorial by a smaller factorial, then the smaller factorial effectively cancels out that many multiplications from the larger. Hence, it is better to implement such functions using prod-range (Recipe 2.5) rather than factorial. The combinatorial is slightly more complex because you want to cancel out the large of r and (n - r).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.80.45