Why do the following statements give different outputs in Java?

joe :

For some values of x (x is of type long),

 x %= (1e9+7);

and

 x %= 1_000_000_007;

give different answers. Any idea why that could be?

Also, is this underscore format (1_000_000_007) common across languages? Are there advantages to it, apart from enhanced readability?

kaya3 :

This is because 1e9 is a double literal, and not every long value can be exactly represented as a double, so there is a loss of precision due to an implicit conversion from long to double.

According to the language specification, x %= d is equivalent to x = (long) (x % d) when x is a variable of type long and d is of type double. The remainder operation also performs binary numeric prommotion on the operands, which converts x to type double.

Since double is a double-precision IEEE 754 floating-point number, it has 53 bits of precision for the mantissa, which is insufficient to represent all 64 bits of precision a long value may require. Put another way, both double and long use 64 bits, but there are many double values which are not long values, therefore there must also be many long values which are not double values. So the implicit conversion from long to double can result in a loss of precision for values greater than 253 or less than -253.

By the way, because of the remainder operation, the error due to loss of precision could be up to 109 + 7 itself. For the input value 9_223_372_036_563_603_804L the error is 999_999_659, for example.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=477493&siteId=1