Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用BigInteger和递归查找幂B_Java_Recursion_Biginteger - Fatal编程技术网

Java 使用BigInteger和递归查找幂B

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);

这是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);
    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的结果吗?当然可以。如此庞大的计算非常耗时。给点时间。