-2

I have a simple program for calculating the x to the power of y.

    public static int calculatePower(int x, int y) {

    int result = 1;

    if (y == 0)
        return result;
    for (int i = 1; i <= y; i++) {

        result = result * x;
    }

    return result;
}

When i pass the parameters as 4 and 15, i get the value back as 1073741824. But when the parameters are 4 and 16, the value returned is zero.

If the outer range value cannot be stored in int, shouldnt it be retaining the last value - 1073741824 ?

  • No, Java just allows numbers to overflow without signaling it. – kumesana Mar 21 '19 at 12:51
  • why should it be that value? [15.17.1. Multiplication Operator *](https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.17.1): *"If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format"* – user85421 Mar 21 '19 at 12:51
  • how could it retain the last value, you re-declare and initialize the variable each time you call the method. – Stultuske Mar 21 '19 at 12:51
  • A solution would be to write unsafe and safe versions depending on your need. You can make it so it throws an exception if your checks fail. The other way would just make sure its well documented that their is a limit to its usage if you are looking for performance pinching, i.e calculating stuff for netcode or whatever. – Mr00Anderson Mar 21 '19 at 12:54
  • See also: https://stackoverflow.com/questions/7215411/multiplication-of-two-ints-overflowing-to-result-in-a-negative-number – Thomas Bitonti Mar 21 '19 at 12:54
  • @Stultuske i initialize it at the beginning only..not sure what you are saying...can you please elaborate – Karthik Srivatsan Mar 21 '19 at 12:55
  • maybe you should have a look at [`Math.multiplyExact()`](https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/lang/Math.html#multiplyExact(int,int)) or [BigInteger](https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/math/BigInteger.html) – user85421 Mar 21 '19 at 12:58

3 Answers3

2

If the outer range value cannot be stored in int, shouldnt it be retaining the last value - 1073741824 ?

No, it's storing the result of the final operation, following the overflow rules listed in the JLS on each operation.

If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.

It's not that the result "defaults" to 0 - it's just that one of the operations ended up overflowing so that the last 32 bits were all 0. All multiplications after that would also result in 0.

You can see that if you add diagnostics to each step:

public class Test {
    public static void main(String[] args) {
        calculatePower(4, 16);
    }

    public static int calculatePower(int x, int y) {
        int result = 1;
        for (int i = 0; i < y; i++) {
            System.out.printf("%d * %d = %d%n", result, x, result * x);
            result = result * x;
        }
        return result;
    }
}

I've simplified your loop at the same time, which means you don't need the base case condition beforehand. Note that neither your original code nor my version handles negative powers - for production code, you should check that and throw an exception.

Output:

1 * 4 = 4
4 * 4 = 16
16 * 4 = 64
64 * 4 = 256
256 * 4 = 1024
1024 * 4 = 4096
4096 * 4 = 16384
16384 * 4 = 65536
65536 * 4 = 262144
262144 * 4 = 1048576
1048576 * 4 = 4194304
4194304 * 4 = 16777216
16777216 * 4 = 67108864
67108864 * 4 = 268435456
268435456 * 4 = 1073741824
1073741824 * 4 = 0

If you raise it to a greater power, e.g. 20, you'll see lines of "0 * 4 = 0" at the end.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

1073741824 + 1 gives you a value -1073741824 because of overflow.

4 and 15 are basically 2^16.

4 and 16 are basically 2^17

2^17 is the double of the 2^ 16. thats why it turns into 1 and all 16 bits are zero. So, all 16 lower bits wiil be picked..

Khalid Shah
  • 3,132
  • 3
  • 20
  • 39
-1

It doesn't default to 0. Your calculation just overflows and ends up in the dead center of the integer range.

Torben
  • 3,805
  • 26
  • 31