Java计算C(n,k)和使用biginteger的阶乘

时间:2018-07-15 07:01:18

标签: java biginteger factorial

我想计算C(n,k)的答案,例如C(10,2)= 10 * 9/2 * 1 = 45 如果我以10之类的小数字测试我的代码,则该代码有效。 但是,当我尝试计算C(1000,900)时,它会编译

  

线程“ main”中的异常java.lang.ArithmeticException:/减零

我看到有人说应该使用BigInteger,但是在尝试之后,它仍然有错误。

例如:我将int factorial更改为BigInteger factorial, 虽然cSelect中的for循环无法将int i更改为BigInteger类型, 结果,答案up/factorial(y)出错。

请帮助我解决此问题。谢谢!

public class Test {

    // Write a factorial function
    static int factorial(int m) {
        int result =1;
        for (int i=2; i<=m; i++) {
            result = result*i;
        }
        return result;
    }

    // Caculate C(x,y)
    static int cSelect(int x, int y) {
        int up=1;
        for(int i=x; i>=(x-y+1); i--) {
            up = up*i;
        }
        return up/factorial(y);
    }

    public static void main(String[] args) {
        System.out.println(cSelect(1000,900));

    }

}

3 个答案:

答案 0 :(得分:3)

您的代码非常容易用factorial进行翻译。从ONE开始,将循环中的每个BigInteger.valueOf(long)乘以i。喜欢,

// Write a factorial function
static BigInteger factorial(int m) {
    BigInteger result = BigInteger.ONE;
    for (int i = 2; i <= m; i++) {
        result = result.multiply(BigInteger.valueOf(i));
    }
    return result;
}

您的其他函数 完全 完全一样,外加factorial(y)的结果除。喜欢,

// Caculate C(x,y)
static BigInteger cSelect(int x, int y) {
    BigInteger up = BigInteger.ONE;
    for (int i = x; i >= (x - y + 1); i--) {
        up = up.multiply(BigInteger.valueOf(i));
    }
    return up.divide(factorial(y));
}

我没有其他改变

  

63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890

我认为这是正确的。

答案 1 :(得分:1)

您必须使用BigInteger进行计算。

您要计算的值大约为6.385051192630516e + 139,并且不能表示为Java基本整数值。

即使结果是可表示的,您除以零错误的原因是除数表达式900! ∗ 100!溢出到零。然后,您将其除以零。

它溢出到零的原因是它可以被2 ^ 32和2 ^ 64整除。可以通过使用一些简单的代数来计算900中2的因数的数量来证明!和100!

答案 2 :(得分:1)

首先,返回值必须为BigInteger,因为C(1000,900)的结果远远超出了int的范围。

第二,您不需要单独的factorial()方法。迭代时进行除法将通过不创建过多的中间值(以进行多次除法为代价,但实际上这样做可能更快)来改善内存占用。

赞:

static BigInteger cSelect(int x, int y) {
    BigInteger v = BigInteger.ONE;
    for (int i = x, j = 1; j <= y; i--, j++)
        v = v.multiply(BigInteger.valueOf(i)).divide(BigInteger.valueOf(j));
    return v;
}

通过向下i向下计数和j向上计数,除法将永远不会占一小部分。

测试

System.out.println(cSelect(10, 2));
System.out.println(cSelect(1000, 900));

输出

45
63850511926305130236698511142022274281262900693853331776286816221524376994750901948920974351797699894319420811933446197797592213357065053890