Reputation: 372
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
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