Question

A method getReminder takes two integers and returns r = (a^5)%m. This method relies in two BigInteger numbers BigInteger.valueOf(a).pow(5) and BigInteger.valueOf(m), but BigInteger was never declared. At the same time, int was declared twice even though just one int is enough. I realize that int doesn't cost much space, I just want to better understand the mechanics.

int myRemainder = getReminder(1000000, 42);
.............
private int getReminder(int a, int m){
int r =BigInteger.valueOf(a).pow(5).remainder(BigInteger.valueOf(m)).intValue(); 
     return r;
}

Is BigInteger created behind the scenes? Is it unnecessary to declare int twice?

Was it helpful?

Solution

While it is faster to type a call chain like this can be difficult to understand. The optimizer will quickly optimize back to the call chain, but provide a better failure stack. It is better to code for readability. As shown below coding with one function call per line yields your answer.

From the Javadoc of BigInteger.

static BigInteger valueOf(long val) Returns a BigInteger whose value is equal to that of the specified long.

The code for this function will include create a new BigInteger to return. These are temporary return values that are never stored to variable, so there is no declaration. The temporary values will be stored on the stack if storage is required.

I see one int declaration, int r. int is also used to specify the return type, as well as the method parameter types. It would be possible to avoid the declaration of r and just return the result of the call chain. The optimizer may avoid the creation of r and just return the value.

As rule of thumb, the optimizer may create temporary variables, and ignore declared variables as necessary. Applying the Law of Demeter and declaring variables as required will give you an idea of which variables are required. This is a possible way this code might be initially parsed:

private int getReminder(int a, int m) {
    BigInteger tmp1 = BigInteger.valueOf(a);
    tmp1 = tmp1.pow(5);
    BigInteger tmp2 = BigInteger.valueOf(m); 
    tmp1 = tmp1.remainder(tmp2);
    int r = tmp1.intValue(); 
    return r;
}

All three variables, tmp1, tmp2 and r, will be allocated on the stack. In a language like c the first level optimization would be to use registers for the variables. This would eliminate the need to allocate memory for them, and avoid the overhead of reading and writing them to memory.

It is possible to get byte code dumps of the code which will show how the allocations were actually done. This may change a different optimization levels. If it gets invoked, the JIT compiler can further optimize the code.

Licensed under: CC-BY-SA with attribution
scroll top