pranay jain
pranay jain

Reputation: 372

Java: Math.pow returning confusing results

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 ?

Upvotes: 1

Views: 148

Answers (1)

matt
matt

Reputation: 12337

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.

Upvotes: 1

Related Questions