Java 使用BigInteger和递归查找幂B
这是Java中的一段代码Java 使用BigInteger和递归查找幂B,java,recursion,biginteger,Java,Recursion,Biginteger,这是Java中的一段代码 import java.util.Scanner; import java.math.*; class power1 { public static void main(String[] args) { Scanner in=new Scanner(System.in); long a=in.nextLong(); BigInteger b=in.nextBigInteger(); long res=power(a,b);
import java.util.Scanner;
import java.math.*;
class power1 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
long a=in.nextLong();
BigInteger b=in.nextBigInteger();
long res=power(a,b);
System.out.println(res);
}
public static long power(long x,BigInteger n) {
int b=(int)(Math.pow(10,9)+7);
long m;
if (n.compareTo(BigInteger.ZERO)==0)
return 1;
if(n.compareTo(BigInteger.ONE)==0)
return x;
if ((n.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO)==0))
{
m = power(x,n.divide(BigInteger.valueOf(2)));
return (m * m)%b;
}
else return (x * power(x,n.subtract(BigInteger.valueOf(1)))%b);
}
}
考虑到它是一个大整数,这应该适用于b的任何值。
但当我输入非常大的b值时,我得到的错误如下
Exception in thread "main" java.lang.StackOverflowError
at java.math.MutableBigInteger.divideKnuth(Unknown Source)
at java.math.MutableBigInteger.divideKnuth(Unknown Source)
at java.math.BigInteger.remainderKnuth(Unknown Source)
at java.math.BigInteger.remainder(Unknown Source)
at java.math.BigInteger.mod(Unknown Source)
有办法解决吗?您应该实现以下算法:
recursivePower(base, exp):
if (exp == 0)
return 1;
if (exp == 1)
return base;
if (exp%2 == 0) {
temp = recursivePower(base, exp/2);
return temp*temp;
temp = recursivePower(base, (exp-1)/2);
return temp*temp*base;
这将大大减少您正在使用的呼叫数。另一件事是扩大堆栈的大小。使用java测试-Xss2048k
运行应用程序-尝试不同的大小
最后但并非最不重要的一点是始终使用BigInteger
public static BigInteger recursivePower (BigInteger base, BigInteger exp) {
if (exp.compareTo(BigInteger.ZERO) == 0)
return BigInteger.ONE;
if (exp.compareTo(BigInteger.ONE) == 0)
return base;
if (exp.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) == 0) {
BigInteger temp = recursivePower(base, exp.divide(BigInteger.valueOf(2)));
return temp.multiply(temp);
}
BigInteger temp = recursivePower(base, (exp.subtract(BigInteger.valueOf(1)).divide(BigInteger.valueOf(2))));
return temp.multiply(temp).multiply(base);
}
public static void main(String []args){
System.out.println(recursivePower(BigInteger.valueOf(2), BigInteger.valueOf(80)).toString());
}
不要使用递归。什么大数字?由于您将ID除以2,因此可能需要一些调用才能到达1,从而导致此stackoverflow(并导致您如此)。这是大量要存储在内存中的biginger yi:
n.mod(biginger.valueOf(2))。compareTo(biginger.ZERO)==0更好地写为!n、 testBit(0)
和n.divide(biginger.valueOf(2))
最好写成n.shiftRight(1)
。性能要好得多。问题:为什么要尝试将long
值提升为BigInteger
指数,并且只将结果作为long
返回?如果基数是1,则无论指数是多少,结果都是1。如果基数为2,则指数值为63时,结果将溢出支持的long
结果范围,并且您几乎不需要BigInteger
来表示该值。对于大于2的基数,结果将以更小的指数值溢出long
。你的方法毫无意义。但是如果我不使用递归,那么计算会增加很多因素。变量b可以是任何东西。它不起作用。代码中有很多小问题。@RickySterling为什么不起作用?这是一个正确的算法。您可以将返回的值转换为函数-single responsibility之外的long。@Xentros…如果可能,请使用main()发布整个程序。我正在为竞赛编写一个程序。它将使用联机编译器进行编译。@RickySterling您打算返回什么?我应该打印2^80的结果吗?当然可以。如此庞大的计算非常耗时。给点时间。