notAChance
notAChance

Reputation: 1430

Math.pow() returning same result with different inputs

I have two empty arrays and some variables:

static int p = 41;
static int q = 67;
static int d = 83;
static int n = p * q;

static int[] encryptedBlocks = new int[charArray.length];
static int[] decryptedArray = new int[charArray.length];

the first of which is filled with the following (I've checked, and it is):

1573
1978
385
1092
1022
857
856
1387
225
606
2293
1339
1630

The second array I'm attempting to fill with the results of an equation in a for loop:

for (int i = 0; i < encryptedBlocks.length; i++) {
            int M = (int)Math.pow(encryptedBlocks[i], d) % n;
            decryptedArray[i] = M;
        }

Problem is I get the same result for M for each iteration.. I'm totally clueless as to what is going on:

2662
2662
2662
2662
2662
2662
2662
2662
2662
2662
2662
2662
2662

Just in case I've double checked encryptedBlocks[i] is indeed the next value each iteration, and it is. Am I missing something in relation to using int and Math.pow()?

First two iteration values for encryptedBlocks[i], d and n:

1573 83 2747 
1978 83 2747

Upvotes: 2

Views: 166

Answers (6)

Aaron Brock
Aaron Brock

Reputation: 4536

Your issue is in the parentheses. This is how the compiler sees what you wrote:

((int) Math.pow(encryptedBlocks[i], d)) % n

It's subtle but what's happening it's casting to an int before taking the modulo. Ordinarily, this wouldn't make a difference but in your case, Math.pow is returning such a large number that casting it to an int truncates it to 2147483647 the maximum value an int can store, then it takes the module of that which will return 2662.

Now, to get the correct answer all we need to do is make sure it calculates the modulo first:

(int) (Math.pow(encryptedBlocks[i], d) % n)

Upvotes: 1

Islam Hassan
Islam Hassan

Reputation: 1736

The result of the power operation is too large to be stored in an integer. 1573 ^ 83 alone is a 122-digits number, and you're doing the mod operation after calculating the power, so it has already overflowed.

If performance is not a concern, you can use BigInteger class. This should work:

BigInteger bigN = BigInteger.valueOf(n);
for (int i = 0; i < encryptedBlocks.length; i++) {
    BigInteger M = BigInteger.valueOf(encryptedBlocks[i]).pow(d).mod( bigN );
    decryptedArray[i] = Integer.valueOf(M.toString());
}
for(int i : decryptedArray) System.out.println(i);

However, BigInteger operations are a bit slow. If you prefer a faster solution you can implement your own power function so you can do a mod operation whenever you're near to overflow an integer value.

Upvotes: 1

Kh.Taheri
Kh.Taheri

Reputation: 957

As mentioned here:

a cast takes precedence over a division operation

Therefore, and as I mentioned in the comments, you have to replace this:

int M = (int)Math.pow(encryptedBlocks[i], d) % n;

With this:

int M = (int)(Math.pow(encryptedBlocks[i], d) % n);

Upvotes: 2

upendra
upendra

Reputation: 111

Yes, you are casting to int to early and that is causing the output to be same always. You can check this in the below output.

package test;

public class MathPow {

    static int p = 41;
    static int q = 67;
    static int d = 83;
    static int n = p * q;

    static int[] encryptedBlocks = {1573,
            1978,
            385,
            1092,
            1022,
            857,
            856,
            1387,
            225,
            606,
            2293,
            1339,
            1630};
    static int[] decryptedArray = new int[13];

    public static void main (String []args){

        for (int i = 0; i < encryptedBlocks.length; i++) {
            double power = Math.pow(encryptedBlocks[i], d);
            System.out.println("Power : "+power);
            double pwer = power % n;
            int M = (int)pwer;
            decryptedArray[i] = M;
            System.out.println("M : "+M);
        }

    }

}

Output when the casting to int is done at the end.

Power : 2.1305119658955046E265
M : 1147
Power : 3.8617294369074443E273
M : 2564
Power : 3.9195891716526933E214
M : 1457
Power : 1.4875753889539146E252
M : 2351
Power : 6.087295034019223E249
M : 2414
Power : 2.7378409793777127E243
M : 982
Power : 2.4849775423187883E243
M : 1073
Power : 6.199351610800489E260
M : 2480
Power : 1.702742606656262E195
M : 923
Power : 8.815111415893474E230
M : 1526
Power : 8.194765730142982E278
M : 704
Power : 3.332636081546012E259
M : 427
Power : 4.0885674380373943E266
M : 235

And output when the casting is done just after the Math.pow operation.

Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662

You can see that the power operation result is same hence M is same as well.

Upvotes: 1

kourouma_coder
kourouma_coder

Reputation: 1098

Just precedence mistake
change this int M = (int)Math.pow(encryptedBlocks[i], d) % n; to
int M = (int)(Math.pow(encryptedBlocks[i], d) % n);

Upvotes: 1

Julian Wright
Julian Wright

Reputation: 705

In your line of code

int M = (int)Math.pow(encryptedBlocks[i], d) % n;

You are calculating Math.pow(encryptedBlocks[i], d), then casting it to an int, then using modulo m on the int result. What you probably wanted to do was only cast to int after all the math was done:

int M = (int) (Math.pow(encryptedBlocks[i], d) % n);

which yields:

1147 2564 1457 2351 2414 982 1073 2480 923 1526 704 427 235

for the given input data.

Upvotes: 2

Related Questions