0

I wrote this line of code:

System.out.println(Math.pow(7, 23) % 143);   // 7^23 mod 143

I expected the output to be 2 but the output was 93.0. Does someone know what I'm doing wrong?

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
Janski_pyc
  • 19
  • 2

3 Answers3

8

The number "overflows" double, which is what Math.pow() expects and returns. Use a BigInteger instead:

BigInteger.valueOf(7)
        .pow(23)
        .mod(BigInteger.valueOf(143))

Or in a single step, as suggested by @Felk:

BigInteger.valueOf(7)
        .modPow(BigInteger.valueOf(23), BigInteger.valueOf(143))
Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
  • 1
    There's one incorrect statement in your answer: "The number overflows double". Being around 2.7e19, it's well within the `double` range, but can't be expressed with the necessary precision. So the BigInteger solution is the straightforward way to go. – Ralf Kleberhoff Sep 20 '17 at 18:48
  • @RalfKleberhoff Yes, you're right. I just put that in quotes, as Andy Turner nailed it down already. Thanks! – Costi Ciudatu Sep 20 '17 at 20:52
3

The result of Math.pow is a double, which has 64 bits; 53 of those are mantissa bits. This means that any integer greater than 2^53-1 = 9007199254740991 can't be represented precisely as a double.

7^23 is larger than 2^53-1 (it's just a bit larger than 2^64, actually), so it can't be represented precisely. As such, the result of the % is not what you expect.

Use BigInteger instead, as @Costi has already suggested.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

Use a Modular exponentiation algorithm if the intermediate exponentiation result is too large to hold in a variable.

System.out.println(powMod(7, 23, 143)); // = 2

// Example from Wikipedia with minor changes
private static int powMod(int base, int exponent, int modulus) {
    if (modulus == 1)
        return 0;

    base %= modulus;
    int result = 1;
    while (exponent > 0) {
        if ((exponent & 1) == 1)
            result = (result * base) % modulus;
        exponent >>= 1;
        base = (base * base) % modulus;
    }
    return result;
}
Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50