计算可能的组合数 - C#

时间:2015-11-22 10:14:11

标签: c# combinations

我试图计算可能组合的数量,所以我在这里使用一些数学(精确的阶乘)。例如,如果我有50个数字并且我想将它们组织成5个组,那么可以制作多少组(组合)。我使用这个公式:while true: x = input("Enter your data in the form of [text] [number]: ") if len(x.split()) > 1 and x.split()[0].isdigit(): break ,但是这个特定的例子会出现错误。它说禁止除以零。如何管理这项工作? 这是我的代码:

allNumbers! / (allNumbers - PerGroup)!

3 个答案:

答案 0 :(得分:2)

Enumerable.Range(1,int.MaxValue).Contains(b/n)检查不检查该值是否有效,因为b / n已经计算并且此时存储为int。

由于变量n溢出并变为零,因此除以零。在下面的代码中,您可以看到溢出是如何发生的。

using System;

public class Test
{
    public static void Main()
    {
        int n = 1;
        for (int i = 1; i <= 50; i++) {
            n *= i;
            Console.WriteLine("i = {0}, n = {1}", i, n);
        }
    }
}

输出:

i = 1, n = 1
i = 2, n = 2
i = 3, n = 6
i = 4, n = 24
i = 5, n = 120
i = 6, n = 720
i = 7, n = 5040
i = 8, n = 40320
i = 9, n = 362880
i = 10, n = 3628800
i = 11, n = 39916800
i = 12, n = 479001600
i = 13, n = 1932053504
i = 14, n = 1278945280
i = 15, n = 2004310016
i = 16, n = 2004189184
i = 17, n = -288522240
i = 18, n = -898433024
i = 19, n = 109641728
i = 20, n = -2102132736
i = 21, n = -1195114496
i = 22, n = -522715136
i = 23, n = 862453760
i = 24, n = -775946240
i = 25, n = 2076180480
i = 26, n = -1853882368
i = 27, n = 1484783616
i = 28, n = -1375731712
i = 29, n = -1241513984
i = 30, n = 1409286144
i = 31, n = 738197504
i = 32, n = -2147483648
i = 33, n = -2147483648
i = 34, n = 0
i = 35, n = 0
i = 36, n = 0
i = 37, n = 0
i = 38, n = 0
i = 39, n = 0
i = 40, n = 0
i = 41, n = 0
i = 42, n = 0
i = 43, n = 0
i = 44, n = 0
i = 45, n = 0
i = 46, n = 0
i = 47, n = 0
i = 48, n = 0
i = 49, n = 0
i = 50, n = 0

答案 1 :(得分:1)

由于allNumbers!始终包含(allNumbers - PerGroup)!,为什么不将它们从开头排除。

int b = 1;

if (allNumbers - PerGroup == 0)
{
      return 1;
}
else if (allNumbers - PerGroup == 1)
{
      return allNumbers;
}
else
{
      for (int i = (allNumbers - PerGroup + 1); i <= allNumbers; i++)     
      {
             b *= i;
      }

      return b;
}

答案 2 :(得分:0)

我猜错误是OutOfMemoryException,因为你创建了大量不必要的integers。 (Enumerable.Range(1,int.MaxValue))请注意每个int从您的记忆中获取4个字节。

我不确定你在那里尝试做什么,但你可以使用double类型,所以如果数字变得非常大,它只会给你PositiveInfinity

或者您可以使用checked通过try和catch控制整数溢出。

另一种方法是在整数溢出发生时预先计算数字。例如,int的阶乘14将溢出,而long的阶乘22将溢出。

此外,您不必为循环写两次。你可以用这个方法。

您无需检查allNumbers - PerGroup == 0以防止零分割。这不会发生,因为0的阶乘是1,当输入为0时,我们的阶乘实现按性质返回1! (因为for循环在这种情况下从不迭代,计数器从1开始。)

private static int Cominations(int allNumbers, int perGroup)
{
    if(allNumbers > 13)
    {
        Console.WriteLine("Too big number!");
        return -1;
    }

    return Factorial(allNumbers)/Factorial(allNumbers - perGroup);
}

private static int Factorial(int number)
{
    int n = 1;

    for (int i = 1; i < number; i++)
    {
        n *= i;
    }

    return n; // returns 1 when number is 0
}

如果要计算较大数字的阶乘,请使用System.Numberics命名空间中的BigInteger类型。

using System.Numerics;

//...

private static BigInteger Factorial(int number)
{
    BigInteger n = 1;

    for (int i = 1; i < number; i++)
    {
        n *= i;
    }

    return n;
}