Java 用双整数计算 C(n,k) 和阶乘
Java Compute C(n,k) and factorial with biginteger
我想计算C(n,k)的答案,例如C(10,2)=10*9/2*1 = 45
如果我用像 10 这样的小数字测试我的代码,代码就可以工作。
但是,当我尝试计算 C(1000,900) 时,它会编译
Exception in thread "main" java.lang.ArithmeticException: / by zero
我看到有人说应该使用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));
}
}
您的代码很容易翻译成 factorial
。从 ONE
开始,为循环中的每个 i
乘以 BigInteger.valueOf(long)
。喜欢,
// 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
我认为是正确的。
您必须使用 BigInteger 进行计算。
您尝试计算的值约为 6.385051192630516e+139,它不能表示为 Java 原始整数值。
即使结果是可表示的,您得到被零除错误的原因是除数表达式 900! ∗ 100!
溢出为零。然后除以那个零。
它溢出为零的原因是它可以被2^32和2^64整除。这可以通过使用一些简单的代数来计算 900 中 2 的因数个数来证明!和 100!
首先,return 的值必须是 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
我想计算C(n,k)的答案,例如C(10,2)=10*9/2*1 = 45 如果我用像 10 这样的小数字测试我的代码,代码就可以工作。 但是,当我尝试计算 C(1000,900) 时,它会编译
Exception in thread "main" java.lang.ArithmeticException: / by zero
我看到有人说应该使用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));
}
}
您的代码很容易翻译成 factorial
。从 ONE
开始,为循环中的每个 i
乘以 BigInteger.valueOf(long)
。喜欢,
// 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
我认为是正确的。
您必须使用 BigInteger 进行计算。
您尝试计算的值约为 6.385051192630516e+139,它不能表示为 Java 原始整数值。
即使结果是可表示的,您得到被零除错误的原因是除数表达式 900! ∗ 100!
溢出为零。然后除以那个零。
它溢出为零的原因是它可以被2^32和2^64整除。这可以通过使用一些简单的代数来计算 900 中 2 的因数个数来证明!和 100!
首先,return 的值必须是 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