1

I am looking into Math.pow() function in Java but the following code gives different results as shown below respectively.

Case 1:

BigDecimal divisor = new BigDecimal(Math.pow(10,9)+7);
BigDecimal dividend = new BigDecimal(1000000000543543509L);
System.out.println(dividend.remainder(divisor)); // 543543558

Case 2:

System.out.println((1000000000543543509L%((int)Math.pow(10,9)+7))+""); 
//543543558

Case 3:

System.out.println((1000000000543543509L%(Math.pow(10,9)+7))+""); //5.43543601E8

Why do I get different results in Case 2 and 3 but same in Case 1 and 2? Which of the above cases is most accurate ?

pranay jain
  • 352
  • 1
  • 2
  • 15
  • 2
    Possible duplicate of [calculating powers in Java](https://stackoverflow.com/questions/8071363/calculating-powers-in-java) – Naman Sep 28 '17 at 19:08
  • What do you think happens when you do `long a` and `double b`, the calculate `a%b`? Is b treated as a long, or is a treated as a double? – matt Sep 28 '17 at 19:17
  • 1
    @nullpointer The problem seems to be the large long that gets cast to double. – matt Sep 28 '17 at 19:23

1 Answers1

1

In the first two cases, the value of the long retains all of the precision of a long. In the third case, the long is cast to a double, and some of the precision is lost. Note that pow returns a double, and double + int causes the int to be cast to a double. Similarly long%double causes the long to be cast to a double.

We can demonstrate the consequence by performing the cast explicitly:

System.out.println((long)((double)1000000000543543509L));
#1000000000543543552

You can verify the value is what op gets by using modulo.

System.out.println(1000000000543543552L%((int)(Math.pow(10, 9) + 7)));
#543543601

So the problem isn't pow, but the long that doesn't fit in a double.

More generally, if we consult the jls on Widening Primitive Conversion we can see that long can be promoted to double (or float) without an explicit cast. This is because it doesn't lose any magnitude information. Although, as this example shows, you can lose some precision.

matt
  • 10,892
  • 3
  • 22
  • 34