为什么在此Java函数中2乘31的幂返回负数?

时间:2018-10-06 18:14:27

标签: java tail-recursion pow negative-number

分配:

  

编写一个递归函数recPow,在Java中n> = 0时计算2n。该函数将具有以下配置文件:

public static int recPow(int n)
  

该功能必须考虑所有情况并进行详尽的测试。

我的问题

我不明白为什么我输入recPow(31)而不是2147483648时我的代码为什么返回-2147483648。我知道你们中有些人可能会告诉我改用long而不是int,但是我相信由于作业的繁琐我需要坚持int。如果有人能帮助我理解为什么会发生这种情况,我从来就不是很好的计算数字,我将对此表示非常感谢。

另外-较大的指数返回0(但是我认为这可能与我们需要使用int vs longs的事实有关。)

我的代码

public static int baseNum = 2, powResult = 1;

public static int recPow(int n) {
    //if the int is not bigger than 0 
    //must only accept ints
    if (n < 0) {
        throw new IllegalArgumentException("n has to be > 0");
    } else {
        //recursion here
        //base number = 2
        if (n==0) {
            return powResult;
        } else {
            powResult = powResult * baseNum;
            return recPow(n - 1);
        }
    }
}

2 个答案:

答案 0 :(得分:3)

  

较大的指数返回0(但是我认为这可能与我们需要使用int vs longs的事实有关。)

正确。

int i = (int) 2147483648L; // -2147483648 due to over flow
int j = i * 2; // 0 due to overflow.

您可以使用long,但这有相同的问题,但是值较高。

public static long recPower(int baseNum, int power) {
    if (power < 0) throw new IllegalArgumentException();
    return power == 0 ? 1L : baseNum * recPower(baseNum, power - 1);
}

检查溢出的一种方法是查看

public static long recPower(int baseNum, int power) {
    if (power < 0) throw new IllegalArgumentException();
    return power == 0 ? 1L : baseNum * recPower(baseNum, power - 1);
}

或检查是否溢出

public static long recPower(int baseNum, int power) {
    if (power < 0) throw new IllegalArgumentException();
    return power == 0 ? 1L 
           : Math.multiplyExact(baseNum, recPower(baseNum, power - 1));
}

您可以使用BigInteger,它的限制要大得多。

答案 1 :(得分:2)

这是由于int数据类型的溢出引起的。

Java的int大小为32位,因此范围是-2,147,483,648至2,147,483,647。

2 ^ 31 = 2147483648

所以它溢出到-2147483648 因为2,147,483,647的二进制值为01111111111111111111111111111111111(一个零和31个),其中第一位是“符号位”(2的补码形式)。

如果您尝试超出此限制(2,147,483,647)1(即为其添加1),则会将符号位更改为1,从而使int为负。

因此它将变为10000000000000000000000000000000(1个1和31个零),为您提供答案-2147483648。