Efficiently returns the binomial coefficient, often also referred to as "n over k" or "n choose k". - Java java.lang

Java examples for java.lang:Math Operation

Description

Efficiently returns the binomial coefficient, often also referred to as "n over k" or "n choose k".

Demo Code

/**   Basic numeric operations not included in standard Java run-time library.
 *
 *   <p>/*from   w  w  w.j  ava 2  s .c o m*/
 *   The binomial methods are modified from those in the Colt library.
 *   </p>
 *
 *   <p>
 *   The following methods for trigonometric functions come from the
 *   Sfun class written by Visual Numerics.
 *   </p>
 *
 *   <ul>
 *   <li>acosh</li>
 *   <li>asinh</li>
 *   <li>atanh</li>
 *   <li>cot</li>
 *   <li>cosh</li>
 *   <li>sinh</li>
 *   <li>tanh</li>
 *   </ul>
 *
 *   <p>
 *   These methods are covered by the following license.
 *   </p>
 *
 * -------------------------------------------------------------------------
 *   $Id: Sfun.java,v 1.1.1.1 1999/03/05 21:43:39 brophy Exp $
 * -------------------------------------------------------------------------
 * Copyright (c) 1997 - 1998 by Visual Numerics, Inc. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software is freely
 * granted by Visual Numerics, Inc., provided that the copyright notice
 * above and the following warranty disclaimer are preserved in human
 * readable form.
 *
 * Because this software is licensed free of charge, it is provided
 * "AS IS", with NO WARRANTY.  TO THE EXTENT PERMITTED BY LAW, VNI
 * DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO ITS PERFORMANCE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * VNI WILL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER ARISING OUT OF THE USE
 * OF OR INABILITY TO USE THIS SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, PUNITIVE, AND EXEMPLARY DAMAGES, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * -------------------------------------------------------------------------
 */

public class Main{
    public static void main(String[] argv) throws Exception{
        double n = 2.45678;
        long k = 2;
        System.out.println(binomial(n,k));
    }
    /**   Efficiently returns the binomial coefficient, often also referred to as "n over k" or "n choose k".
     *
     *   <p>
     *   The binomial coefficient is defined as <tt>(n * n-1 * ... * n-k+1 ) / ( 1 * 2 * ... * k )</tt>.
     *   </p>
     *
     *   <ul>
     *   <li>k<0<tt>: <tt>0</tt>.</li>
     *   <li>k==0<tt>: <tt>1</tt>.</li>
     *   <li>k==1<tt>: <tt>n</tt>.</li>
     *   <li>else: <tt>(n * n-1 * ... * n-k+1 ) / ( 1 * 2 * ... * k )</tt>.</li>
     *   </ul>
     *
     *   @return      The binomial coefficient.
     */

    public static double binomial(double n, long k) {
        if (k < 0)
            return 0.0D;
        if (k == 0)
            return 1.0D;
        if (k == 1)
            return (double) n;

        // Compute binomial(n,k) =
        // (n * n-1 * ... * n-k+1 ) / ( 1 * 2 * ... * k )

        double a = n - k + 1;
        double b = 1.0D;
        double binomial = 1.0D;

        for (long i = k; i-- > 0;) {
            binomial *= (a++) / (b++);
        }

        return binomial;
    }
    /**   Efficiently returns the binomial coefficient, often also referred to as "n over k" or "n choose k".
     *
     *   <p>
     *   The binomial coefficient is defined as
     *   </p>
     *   <ul>
     *   <li>k<0<tt>: <tt>0</tt>.</li>
     *   <li>k==0 || k==n<tt>: <tt>1</tt>.</li>
     *   <li>k==1 || k==n-1<tt>: <tt>n</tt>.</li>
     *   <li>else: <tt>(n * n-1 * ... * n-k+1 ) / ( 1 * 2 * ... * k )</tt>.</li>
     *   </ul>
     *
     *   @return       The binomial coefficient.
     */

    public static double binomial(long n, long k) {
        if (k < 0)
            return 0.0D;
        if ((k == 0) || (k == n))
            return 1.0D;
        if ((k == 1) || (k == (n - 1)))
            return n;

        // try quick version and see whether we get numeric overflows.
        // factorial(..) is O(1); requires no loop; only a table lookup.
        if (n > k) {
            int max = Factorial.longFactorials.length
                    + Factorial.doubleFactorials.length;

            if (n < max) { // if (n! < inf && k! < inf)
                double n_fac = Factorial.factorial((int) n);
                double k_fac = Factorial.factorial((int) k);
                double n_minus_k_fac = Factorial.factorial((int) (n - k));
                double nk = n_minus_k_fac * k_fac;

                if (nk != Double.POSITIVE_INFINITY) { // no numeric overflow?
                                                      // now this is completely safe and accurate
                    return n_fac / nk;
                }
            }
            if (k > (n / 2))
                k = n - k; // quicker
        }

        // binomial(n,k) = (n * n-1 * ... * n-k+1 ) / ( 1 * 2 * ... * k )

        long a = n - k + 1;
        long b = 1;
        double binomial = 1.0D;

        for (long i = k; i-- > 0;) {
            binomial *= ((double) (a++)) / (b++);
        }

        return binomial;
    }
}

Related Tutorials