0

I'm trying to use Java to calculate the value of the value of 2^{61} - 1.

Here's my code

import java.lang.Math;

class Main {
  public static void main(String[] args) {
    long x = (long) (Math.pow(2, 61) - 1);
    System.out.println(x);
  }
}

The output is 2305843009213693952, which is wrong.

The answer should be 2305843009213693951.

I'm confused as to why this is the case?

Thanks

Lesiak
  • 22,088
  • 2
  • 41
  • 65
jack klompus
  • 244
  • 1
  • 2
  • 9
  • 1
    What do you get without the cast to `long`? The [API for `pow`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Math.html#pow(double,double)) says, "If both arguments are integers, then the result is exactly equal to the mathematical result of raising the first argument to the power of the second argument if that result can in fact be represented exactly as a double value." Perhaps 2^61 cannot be exactly represented as a double value. – Paul Aug 11 '23 at 17:58
  • 2
    Doubles can only represent integers of up to 52 bits exactly. Actually, that statement is an oversimplification and not strictly true, but true enough for your needs. You can do this in longs almost as simply as `long x = (1L << 61) - 1L;` If you absolutely must use exponentiation whose results are this large then use the `BigInteger` class. – President James K. Polk Aug 11 '23 at 17:58
  • Why dont use Double? – Diego Borba Aug 11 '23 at 17:59
  • the result you want is 60 bits integer however `double` has less mantissa bits so the result is rounded ... – Spektre Aug 12 '23 at 07:42

1 Answers1

4

The issue is with the precision of the double data type when using Math.pow(2, 61). It can't represent 2^{61} accurately, leading to rounding errors.

Instead, use "bit shifting" for accuracy:

class Main {
  public static void main(String[] args) {
    long x = (1L << 61) - 1;
    System.out.println(x);
  }
}

This approach avoids the precision error and gives the correct result.

Dale
  • 1,613
  • 4
  • 22
  • 42