Algorithm for Calculating Binomial Coefficient

前端 未结 5 1987
别跟我提以往
别跟我提以往 2020-12-10 05:30

I need a way of calculating combinations without running out of memory. Here\'s what i have so far.

public static long combination(long n, long k) // nCk
{
          


        
5条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-10 05:51

    Looking at your code, it is no wonder that you will run out of memory quite fast. Your method divideFactorials calls the method factorial and uses as argument the difference "numerator-denominator". That difference is very likely going to be very large according to your code and you will be stuck in a very long loop in your factorial method.

    If it is really just about finding nCk (which I assume because your comment in your code), just use:

    public static long GetnCk(long n, long k)
    {
        long bufferNum = 1;
        long bufferDenom = 1;
    
        for(long i = n; i > Math.Abs(n-k); i--)
        {
            bufferNum *= i;
        }
    
        for(long i = k; i => 1; i--)
        {
            bufferDenom *= i;
        }
    
        return (long)(bufferNom/bufferDenom);
    }
    

    Of course using this method you will run out of range very fast, because a long does not actually support very long numbers, so n and k have to be smaller than 20.

    Supposing that you actually work with very large numbers you could use doubles instead of longs, as the powers become more and more significant.

    Edit: If you use large numbers you could also use Stirling's Formula:

    As n becomes large ln(n!) -> n*ln(n) - n.

    Putting this into code:

    public static double GetnCk(long n, long k)
    {
        double buffern = n*Math.Log(n) - n;
        double bufferk = k*Math.Log(k) - k;
        double bufferkn = Math.Abs(n-k)*Math.Log(Math.Abs(n-k)) - Math.Abs(n-k);
    
        return Math.Exp(buffern)/(Math.Exp(bufferk)*Math.Exp(bufferkn));
    }
    

    I only propose this answer, as you said language independent, the C# code is just used to demonstrate it. Since you need to use large numbers for n and k for this to work, i propose this as a general way for finding the binomial coefficient for large combinations.

    For cases were n and k are both smaller than around 200-300, you should use the answer Victor Mukherjee proposed, as it is exact.

    Edit2: Edited my first code.

提交回复
热议问题